1 2 /// A D API for libgccjit, purely as final class wrapper functions. 3 /// Copyright (C) 2014-2015 Iain Buclaw. 4 5 /// This file is part of gccjitd. 6 7 /// This program is free software: you can redistribute it and/or modify 8 /// it under the terms of the GNU General Public License as published by 9 /// the Free Software Foundation, either version 3 of the License, or 10 /// (at your option) any later version. 11 12 /// This program is distributed in the hope that it will be useful, 13 /// but WITHOUT ANY WARRANTY; without even the implied warranty of 14 /// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 /// GNU General Public License for more details. 16 17 /// You should have received a copy of the GNU General Public License 18 /// along with this program. If not, see <http://www.gnu.org/licenses/>. 19 20 module gccjit.d; 21 22 public import gccjit.c; 23 24 import std.conv : to; 25 import std.string : toStringz; 26 import std.traits : isIntegral, isSigned; 27 28 /// Errors within the API become D exceptions of this class. 29 final class JITError : Exception 30 { 31 @safe pure nothrow this(string msg, Throwable next = null) 32 { 33 super(msg, next); 34 } 35 36 @safe pure nothrow this(string msg, string file, size_t line, Throwable next = null) 37 { 38 super(msg, file, line, next); 39 } 40 } 41 42 /// Class wrapper for gcc_jit_object. 43 /// All JITObject's are created within a JITContext, and are automatically 44 /// cleaned up when the context is released. 45 46 /// The class hierachy looks like this: 47 /// $(OL - JITObject 48 /// $(OL - JITLocation) 49 /// $(OL - JITType 50 /// $(OL - JITStruct)) 51 /// $(OL - JITField) 52 /// $(OL - JITFunction) 53 /// $(OL - JITBlock) 54 /// $(OL - JITRValue 55 /// $(OL - JITLValue 56 /// $(OL - JITParam)))) 57 class JITObject 58 { 59 /// Return the context this JITObject is within. 60 final JITContext getContext() 61 { 62 auto result = gcc_jit_object_get_context(this.m_inner_obj); 63 return new JITContext(result); 64 } 65 66 /// Get a human-readable description of this object. 67 override final string toString() 68 { 69 auto result = gcc_jit_object_get_debug_string(this.m_inner_obj); 70 return to!string(result); 71 } 72 73 protected: 74 // Constructors and getObject are hidden from public. 75 this() 76 { 77 this.m_inner_obj = null; 78 } 79 80 this(gcc_jit_object *obj) 81 { 82 if (!obj) 83 throw new JITError("Unknown error, got bad object"); 84 this.m_inner_obj = obj; 85 } 86 87 final gcc_jit_object *getObject() 88 { 89 return this.m_inner_obj; 90 } 91 92 private: 93 // The actual gccjit object we interface with. 94 gcc_jit_object *m_inner_obj; 95 } 96 97 /// Class wrapper for gcc_jit_location. 98 /// A JITLocation encapsulates a source code locations, so that you can associate 99 /// locations in your language with statements in the JIT-compiled code. 100 class JITLocation : JITObject 101 { 102 /// 103 this() 104 { 105 super(); 106 } 107 108 /// 109 this(gcc_jit_location *loc) 110 { 111 super(gcc_jit_location_as_object(loc)); 112 } 113 114 /// Returns the internal gcc_jit_location object. 115 final gcc_jit_location *getLocation() 116 { 117 // Manual downcast. 118 return cast(gcc_jit_location *)(this.getObject()); 119 } 120 } 121 122 /// The top-level of the API is the JITContext class. 123 124 /// A JITContext instance encapsulates the state of a compilation. 125 /// It goes through two states. 126 /// Initial: 127 /// During which you can set up options on it, and add types, 128 /// functions and code, using the API below. Invoking compile 129 /// on it transitions it to the PostCompilation state. 130 /// PostCompilation: 131 /// When you can call JITContext.release to clean it up. 132 final class JITContext 133 { 134 /// 135 this(bool acquire = true) 136 { 137 if (acquire) 138 this.m_inner_ctxt = gcc_jit_context_acquire(); 139 else 140 this.m_inner_ctxt = null; 141 } 142 143 /// 144 this(gcc_jit_context *context) 145 { 146 if (!context) 147 throw new JITError("Unknown error, got bad context"); 148 this.m_inner_ctxt = context; 149 } 150 151 /// Acquire a JIT-compilation context. 152 static JITContext acquire() 153 { 154 return new JITContext(gcc_jit_context_acquire()); 155 } 156 157 /// Release the context. 158 /// After this call, it's no longer valid to use this JITContext. 159 void release() 160 { 161 gcc_jit_context_release(this.m_inner_ctxt); 162 this.m_inner_ctxt = null; 163 } 164 165 /// Set a string option of the context; see JITStrOption for notes 166 /// on the options and their meanings. 167 /// Params: 168 /// opt = Which option to set. 169 /// value = The new value. 170 void setOption(JITStrOption opt, string value) 171 { 172 gcc_jit_context_set_str_option(this.m_inner_ctxt, opt, value.toStringz()); 173 } 174 175 /// Set an integer option of the context; see JITIntOption for notes 176 /// on the options and their meanings. 177 /// Params: 178 /// opt = Which option to set. 179 /// value = The new value. 180 void setOption(JITIntOption opt, int value) 181 { 182 gcc_jit_context_set_int_option(this.m_inner_ctxt, opt, value); 183 } 184 185 /// Set a boolean option of the context; see JITBoolOption for notes 186 /// on the options and their meanings. 187 /// Params: 188 /// opt = Which option to set. 189 /// value = The new value. 190 void setOption(JITBoolOption opt, bool value) 191 { 192 gcc_jit_context_set_bool_option(this.m_inner_ctxt, opt, value); 193 } 194 195 /// Calls into GCC and runs the build. It can only be called once on a 196 /// given context. 197 /// Returns: 198 /// A wrapper around a .so file. 199 JITResult compile() 200 { 201 auto result = gcc_jit_context_compile(this.m_inner_ctxt); 202 if (!result) 203 throw new JITError(this.getFirstError()); 204 return new JITResult(result); 205 } 206 207 /// Returns: 208 /// The first error message that occurred when compiling the context. 209 string getFirstError() 210 { 211 const char *err = gcc_jit_context_get_first_error(this.m_inner_ctxt); 212 if (err) 213 return to!string(err); 214 return null; 215 } 216 217 /// Dump a C-like representation describing what's been set up on the 218 /// context to file. 219 /// Params: 220 /// path = Location of file to write to. 221 /// update_locations = If true, then also write JITLocation information. 222 void dump(string path, bool update_locations) 223 { 224 gcc_jit_context_dump_to_file(this.m_inner_ctxt, 225 path.toStringz(), 226 update_locations); 227 } 228 229 /// Returns the internal gcc_jit_context object. 230 gcc_jit_context *getContext() 231 { 232 return this.m_inner_ctxt; 233 } 234 235 /// Build a JITType from one of the types in JITTypeKind. 236 JITType getType(JITTypeKind kind) 237 { 238 auto result = gcc_jit_context_get_type(this.m_inner_ctxt, kind); 239 return new JITType(result); 240 } 241 242 /// Build an integer type of a given size and signedness. 243 JITType getIntType(int num_bytes, bool is_signed) 244 { 245 auto result = gcc_jit_context_get_int_type(this.m_inner_ctxt, 246 num_bytes, is_signed); 247 return new JITType(result); 248 } 249 250 /// A way to map a specific int type, using the compiler to 251 /// get the details automatically e.g: 252 /// JITType type = getIntType!size_t(); 253 JITType getIntType(T)() if (isIntegral!T) 254 { 255 return this.getIntType(T.sizeof, isSigned!T); 256 } 257 258 /// Create a reference to a GCC builtin function. 259 JITFunction getBuiltinFunction(string name) 260 { 261 auto result = gcc_jit_context_get_builtin_function(this.m_inner_ctxt, 262 name.toStringz()); 263 return new JITFunction(result); 264 } 265 266 /// Create a new child context of the given JITContext, inheriting a copy 267 /// of all option settings from the parent. 268 /// The returned JITContext can reference objects created within the 269 /// parent, but not vice-versa. The lifetime of the child context must be 270 /// bounded by that of the parent. You should release a child context 271 /// before releasing the parent context. 272 JITContext newChildContext() 273 { 274 auto result = gcc_jit_context_new_child_context(this.m_inner_ctxt); 275 if (!result) 276 throw new JITError("Unknown error creating child context"); 277 return new JITContext(result); 278 } 279 280 /// Make a JITLocation representing a source location, 281 /// for use by the debugger. 282 /// Note: 283 /// You need to enable JITBoolOption.DEBUGINFO on the context 284 /// for these locations to actually be usable by the debugger. 285 JITLocation newLocation(string filename, int line, int column) 286 { 287 auto result = gcc_jit_context_new_location(this.m_inner_ctxt, 288 filename.toStringz(), 289 line, column); 290 return new JITLocation(result); 291 } 292 293 /// Given type "T", build a new array type of "T[N]". 294 JITType newArrayType(JITLocation loc, JITType type, int dims) 295 { 296 auto result = gcc_jit_context_new_array_type(this.m_inner_ctxt, 297 loc ? loc.getLocation() : null, 298 type.getType(), dims); 299 return new JITType(result); 300 } 301 302 /// Ditto 303 JITType newArrayType(JITType type, int dims) 304 { 305 return this.newArrayType(null, type, dims); 306 } 307 308 /// Ditto 309 JITType newArrayType(JITLocation loc, JITTypeKind kind, int dims) 310 { 311 return this.newArrayType(loc, this.getType(kind), dims); 312 } 313 314 /// Ditto 315 JITType newArrayType(JITTypeKind kind, int dims) 316 { 317 return this.newArrayType(null, this.getType(kind), dims); 318 } 319 320 /// Create a field, for use within a struct or union. 321 JITField newField(JITLocation loc, JITType type, string name) 322 { 323 auto result = gcc_jit_context_new_field(this.m_inner_ctxt, 324 loc ? loc.getLocation() : null, 325 type.getType(), 326 name.toStringz()); 327 return new JITField(result); 328 } 329 330 /// Ditto 331 JITField newField(JITType type, string name) 332 { 333 return this.newField(null, type, name); 334 } 335 336 /// Ditto 337 JITField newField(JITLocation loc, JITTypeKind kind, string name) 338 { 339 return this.newField(loc, this.getType(kind), name); 340 } 341 342 /// Ditto 343 JITField newField(JITTypeKind kind, string name) 344 { 345 return this.newField(null, this.getType(kind), name); 346 } 347 348 /// Create a struct type from an array of fields. 349 JITStruct newStructType(JITLocation loc, string name, JITField[] fields...) 350 { 351 // Convert to an array of inner pointers. 352 gcc_jit_field*[] field_p = new gcc_jit_field*[fields.length]; 353 foreach(i, field; fields) 354 field_p[i] = field.getField(); 355 356 // Treat the array as being of the underlying pointers, relying on 357 // the wrapper type being such a pointer internally. 358 auto result = gcc_jit_context_new_struct_type(this.m_inner_ctxt, 359 loc ? loc.getLocation() : null, 360 name.toStringz(), 361 cast(int)fields.length, 362 field_p.ptr); 363 return new JITStruct(result); 364 } 365 366 /// Ditto 367 JITStruct newStructType(string name, JITField[] fields...) 368 { 369 return this.newStructType(null, name, fields); 370 } 371 372 /// Create an opaque struct type. 373 JITStruct newOpaqueStructType(JITLocation loc, string name) 374 { 375 auto result = gcc_jit_context_new_opaque_struct(this.m_inner_ctxt, 376 loc ? loc.getLocation() : null, 377 name.toStringz()); 378 return new JITStruct(result); 379 } 380 381 /// Ditto 382 JITStruct newOpaqueStructType(string name) 383 { 384 return this.newOpaqueStructType(null, name); 385 } 386 387 /// Create a union type from an array of fields. 388 JITType newUnionType(JITLocation loc, string name, JITField[] fields...) 389 { 390 // Convert to an array of inner pointers. 391 gcc_jit_field*[] field_p = new gcc_jit_field*[fields.length]; 392 foreach(i, field; fields) 393 field_p[i] = field.getField(); 394 395 // Treat the array as being of the underlying pointers, relying on 396 // the wrapper type being such a pointer internally. 397 auto result = gcc_jit_context_new_union_type(this.m_inner_ctxt, 398 loc ? loc.getLocation() : null, 399 name.toStringz(), 400 cast(int)fields.length, 401 field_p.ptr); 402 return new JITType(result); 403 } 404 405 /// Ditto 406 JITType newUnionType(string name, JITField[] fields...) 407 { 408 return this.newUnionType(null, name, fields); 409 } 410 411 /// Create a function type. 412 JITType newFunctionType(JITLocation loc, JITType return_type, 413 bool is_variadic, JITType[] param_types...) 414 { 415 // Convert to an array of inner pointers. 416 gcc_jit_type*[] type_p = new gcc_jit_type*[param_types.length]; 417 foreach(i, type; param_types) 418 type_p[i] = type.getType(); 419 420 // Treat the array as being of the underlying pointers, relying on 421 // the wrapper type being such a pointer internally. 422 auto result = gcc_jit_context_new_function_ptr_type(this.m_inner_ctxt, 423 loc ? loc.getLocation() : null, 424 return_type.getType(), 425 cast(int)param_types.length, 426 type_p.ptr, is_variadic); 427 return new JITType(result); 428 } 429 430 /// Ditto 431 JITType newFunctionType(JITType return_type, bool is_variadic, 432 JITType[] param_types...) 433 { 434 return this.newFunctionType(null, return_type, is_variadic, 435 param_types); 436 } 437 438 /// Ditto 439 JITType newFunctionType(JITLocation loc, JITTypeKind return_kind, 440 bool is_variadic, JITType[] param_types...) 441 { 442 return this.newFunctionType(loc, this.getType(return_kind), 443 is_variadic, param_types); 444 } 445 446 /// Ditto 447 JITType newFunctionType(JITTypeKind return_kind, bool is_variadic, 448 JITType[] param_types...) 449 { 450 return this.newFunctionType(null, this.getType(return_kind), 451 is_variadic, param_types); 452 } 453 454 /// Create a function parameter. 455 JITParam newParam(JITLocation loc, JITType type, string name) 456 { 457 auto result = gcc_jit_context_new_param(this.m_inner_ctxt, 458 loc ? loc.getLocation() : null, 459 type.getType(), 460 name.toStringz()); 461 return new JITParam(result); 462 } 463 464 /// Ditto 465 JITParam newParam(JITType type, string name) 466 { 467 return this.newParam(null, type, name); 468 } 469 470 /// Ditto 471 JITParam newParam(JITLocation loc, JITTypeKind kind, string name) 472 { 473 return this.newParam(loc, this.getType(kind), name); 474 } 475 476 /// Ditto 477 JITParam newParam(JITTypeKind kind, string name) 478 { 479 return this.newParam(null, this.getType(kind), name); 480 } 481 482 /// Create a function. 483 JITFunction newFunction(JITLocation loc, JITFunctionKind kind, JITType return_type, 484 string name, bool is_variadic, JITParam[] params...) 485 { 486 // Convert to an array of inner pointers. 487 gcc_jit_param*[] param_p = new gcc_jit_param*[params.length]; 488 foreach(i, param; params) 489 param_p[i] = param.getParam(); 490 491 // Treat the array as being of the underlying pointers, relying on 492 // the wrapper type being such a pointer internally. 493 auto result = gcc_jit_context_new_function(this.m_inner_ctxt, 494 loc ? loc.getLocation() : null, 495 kind, return_type.getType(), 496 name.toStringz(), 497 cast(int)params.length, 498 param_p.ptr, is_variadic); 499 return new JITFunction(result); 500 } 501 502 /// Ditto 503 JITFunction newFunction(JITFunctionKind kind, JITType return_type, 504 string name, bool is_variadic, JITParam[] params...) 505 { 506 return this.newFunction(null, kind, return_type, name, is_variadic, params); 507 } 508 509 /// Ditto 510 JITFunction newFunction(JITLocation loc, JITFunctionKind kind, JITTypeKind return_kind, 511 string name, bool is_variadic, JITParam[] params...) 512 { 513 return this.newFunction(loc, kind, this.getType(return_kind), 514 name, is_variadic, params); 515 } 516 517 /// Ditto 518 JITFunction newFunction(JITFunctionKind kind, JITTypeKind return_kind, 519 string name, bool is_variadic, JITParam[] params...) 520 { 521 return this.newFunction(null, kind, this.getType(return_kind), 522 name, is_variadic, params); 523 } 524 525 /// 526 JITLValue newGlobal(JITLocation loc, JITGlobalKind global_kind, 527 JITType type, string name) 528 { 529 auto result = gcc_jit_context_new_global(this.m_inner_ctxt, 530 loc ? loc.getLocation() : null, 531 global_kind, type.getType(), 532 name.toStringz()); 533 return new JITLValue(result); 534 } 535 536 /// Ditto 537 JITLValue newGlobal(JITGlobalKind global_kind, JITType type, string name) 538 { 539 return this.newGlobal(null, global_kind, type, name); 540 } 541 542 /// Ditto 543 JITLValue newGlobal(JITLocation loc, JITGlobalKind global_kind, 544 JITTypeKind kind, string name) 545 { 546 return this.newGlobal(loc, global_kind, this.getType(kind), name); 547 } 548 549 /// Ditto 550 JITLValue newGlobal(JITGlobalKind global_kind, JITTypeKind kind, string name) 551 { 552 return this.newGlobal(null, global_kind, this.getType(kind), name); 553 } 554 555 /// Given a JITType, which must be a numeric type, get an integer constant 556 /// as a JITRValue of that type. 557 JITRValue newRValue(JITType type, int value) 558 { 559 auto result = gcc_jit_context_new_rvalue_from_int(this.m_inner_ctxt, 560 type.getType(), value); 561 return new JITRValue(result); 562 } 563 564 /// Ditto 565 JITRValue newRValue(JITTypeKind kind, int value) 566 { 567 return newRValue(this.getType(kind), value); 568 } 569 570 /// Given a JITType, which must be a floating point type, get a floating 571 /// point constant as a JITRValue of that type. 572 JITRValue newRValue(JITType type, double value) 573 { 574 auto result = gcc_jit_context_new_rvalue_from_double(this.m_inner_ctxt, 575 type.getType(), value); 576 return new JITRValue(result); 577 } 578 579 /// Ditto 580 JITRValue newRValue(JITTypeKind kind, double value) 581 { 582 return newRValue(this.getType(kind), value); 583 } 584 585 /// Given a JITType, which must be a pointer type, and an address, get a 586 /// JITRValue representing that address as a pointer of that type. 587 JITRValue newRValue(JITType type, void *value) 588 { 589 auto result = gcc_jit_context_new_rvalue_from_ptr(this.m_inner_ctxt, 590 type.getType(), value); 591 return new JITRValue(result); 592 } 593 594 /// Ditto 595 JITRValue newRValue(JITTypeKind kind, void *value) 596 { 597 return newRValue(this.getType(kind), value); 598 } 599 600 /// Make a JITRValue for the given string literal value. 601 /// Params: 602 /// value = The string literal. 603 JITRValue newRValue(string value) 604 { 605 auto result = gcc_jit_context_new_string_literal(this.m_inner_ctxt, 606 value.toStringz()); 607 return new JITRValue(result); 608 } 609 610 /// Given a JITType, which must be a numeric type, get the constant 0 as a 611 /// JITRValue of that type. 612 JITRValue zero(JITType type) 613 { 614 auto result = gcc_jit_context_zero(this.m_inner_ctxt, type.getType()); 615 return new JITRValue(result); 616 } 617 618 /// Ditto 619 JITRValue zero(JITTypeKind kind) 620 { 621 return this.zero(this.getType(kind)); 622 } 623 624 /// Given a JITType, which must be a numeric type, get the constant 1 as a 625 /// JITRValue of that type. 626 JITRValue one(JITType type) 627 { 628 auto result = gcc_jit_context_one(this.m_inner_ctxt, type.getType()); 629 return new JITRValue(result); 630 } 631 632 /// Ditto 633 JITRValue one(JITTypeKind kind) 634 { 635 return this.one(this.getType(kind)); 636 } 637 638 /// Given a JITType, which must be a pointer type, get a JITRValue 639 /// representing the NULL pointer of that type. 640 JITRValue nil(JITType type) 641 { 642 auto result = gcc_jit_context_null(this.m_inner_ctxt, type.getType()); 643 return new JITRValue(result); 644 } 645 646 /// Ditto 647 JITRValue nil(JITTypeKind kind) 648 { 649 return this.nil(this.getType(kind)); 650 } 651 652 /// Generic unary operations. 653 654 /// Make a JITRValue for the given unary operation. 655 /// Params: 656 /// loc = The source location, if any. 657 /// op = Which unary operation. 658 /// type = The type of the result. 659 /// a = The input expression. 660 JITRValue newUnaryOp(JITLocation loc, JITUnaryOp op, JITType type, JITRValue a) 661 { 662 auto result = gcc_jit_context_new_unary_op(this.m_inner_ctxt, 663 loc ? loc.getLocation() : null, 664 op, type.getType(), 665 a.getRValue()); 666 return new JITRValue(result); 667 } 668 669 /// Ditto 670 JITRValue newUnaryOp(JITUnaryOp op, JITType type, JITRValue a) 671 { 672 return this.newUnaryOp(null, op, type, a); 673 } 674 675 /// Generic binary operations. 676 677 /// Make a JITRValue for the given binary operation. 678 /// Params: 679 /// loc = The source location, if any. 680 /// op = Which binary operation. 681 /// type = The type of the result. 682 /// a = The first input expression. 683 /// b = The second input expression. 684 JITRValue newBinaryOp(JITLocation loc, JITBinaryOp op, 685 JITType type, JITRValue a, JITRValue b) 686 { 687 auto result = gcc_jit_context_new_binary_op(this.m_inner_ctxt, 688 loc ? loc.getLocation() : null, 689 op, type.getType(), 690 a.getRValue(), 691 b.getRValue()); 692 return new JITRValue(result); 693 } 694 695 /// Ditto 696 JITRValue newBinaryOp(JITBinaryOp op, JITType type, JITRValue a, JITRValue b) 697 { 698 return this.newBinaryOp(null, op, type, a, b); 699 } 700 701 /// Generic comparisons. 702 703 /// Make a JITRValue of boolean type for the given comparison. 704 /// Params: 705 /// loc = The source location, if any. 706 /// op = Which comparison. 707 /// a = The first input expression. 708 /// b = The second input expression. 709 JITRValue newComparison(JITLocation loc, JITComparison op, 710 JITRValue a, JITRValue b) 711 { 712 auto result = gcc_jit_context_new_comparison(this.m_inner_ctxt, 713 loc ? loc.getLocation() : null, 714 op, a.getRValue(), 715 b.getRValue()); 716 return new JITRValue(result); 717 } 718 719 /// Ditto 720 JITRValue newComparison(JITComparison op, JITRValue a, JITRValue b) 721 { 722 return this.newComparison(null, op, a, b); 723 } 724 725 /// The most general way of creating a function call. 726 JITRValue newCall(JITLocation loc, JITFunction func, JITRValue[] args...) 727 { 728 // Convert to an array of inner pointers. 729 gcc_jit_rvalue*[] arg_p = new gcc_jit_rvalue*[args.length]; 730 foreach(i, arg; args) 731 arg_p[i] = arg.getRValue(); 732 733 // Treat the array as being of the underlying pointers, relying on 734 // the wrapper type being such a pointer internally. 735 auto result = gcc_jit_context_new_call(this.m_inner_ctxt, 736 loc ? loc.getLocation() : null, 737 func.getFunction(), 738 cast(int)args.length, 739 arg_p.ptr); 740 return new JITRValue(result); 741 } 742 743 /// Ditto 744 JITRValue newCall(JITFunction func, JITRValue[] args...) 745 { 746 return this.newCall(null, func, args); 747 } 748 749 /// Calling a function through a pointer. 750 JITRValue newCall(JITLocation loc, JITRValue ptr, JITRValue[] args...) 751 { 752 // Convert to an array of inner pointers. 753 gcc_jit_rvalue*[] arg_p = new gcc_jit_rvalue*[args.length]; 754 foreach(i, arg; args) 755 arg_p[i] = arg.getRValue(); 756 757 // Treat the array as being of the underlying pointers, relying on 758 // the wrapper type being such a pointer internally. 759 auto result = gcc_jit_context_new_call_through_ptr(this.m_inner_ctxt, 760 loc ? loc.getLocation() : null, 761 ptr.getRValue(), 762 cast(int)args.length, 763 arg_p.ptr); 764 return new JITRValue(result); 765 } 766 767 /// Ditto 768 JITRValue newCall(JITRValue ptr, JITRValue[] args...) 769 { 770 return this.newCall(null, ptr, args); 771 } 772 773 /// Type-coercion. 774 /// Currently only a limited set of conversions are possible. 775 /// int <=> float and int <=> bool. 776 JITRValue newCast(JITLocation loc, JITRValue expr, JITType type) 777 { 778 auto result = gcc_jit_context_new_cast(this.m_inner_ctxt, 779 loc ? loc.getLocation() : null, 780 expr.getRValue(), type.getType()); 781 return new JITRValue(result); 782 } 783 784 /// Ditto 785 JITRValue newCast(JITRValue expr, JITType type) 786 { 787 return this.newCast(null, expr, type); 788 } 789 790 /// Ditto 791 JITRValue newCast(JITLocation loc, JITRValue expr, JITTypeKind kind) 792 { 793 return this.newCast(loc, expr, this.getType(kind)); 794 } 795 796 /// Ditto 797 JITRValue newCast(JITRValue expr, JITTypeKind kind) 798 { 799 return this.newCast(null, expr, this.getType(kind)); 800 } 801 802 /// Accessing an array or pointer through an index. 803 /// Params: 804 /// loc = The source location, if any. 805 /// ptr = The pointer or array. 806 /// index = The index within the array. 807 JITLValue newArrayAccess(JITLocation loc, JITRValue ptr, JITRValue index) 808 { 809 auto result = gcc_jit_context_new_array_access(this.m_inner_ctxt, 810 loc ? loc.getLocation() : null, 811 ptr.getRValue(), index.getRValue()); 812 return new JITLValue(result); 813 } 814 815 /// Ditto 816 JITLValue newArrayAccess(JITRValue ptr, JITRValue index) 817 { 818 return this.newArrayAccess(null, ptr, index); 819 } 820 821 private: 822 gcc_jit_context *m_inner_ctxt; 823 } 824 825 /// Class wrapper for gcc_jit_field 826 class JITField : JITObject 827 { 828 /// 829 this() 830 { 831 super(); 832 } 833 834 /// 835 this(gcc_jit_field *field) 836 { 837 super(gcc_jit_field_as_object(field)); 838 } 839 840 /// Returns the internal gcc_jit_field object. 841 final gcc_jit_field *getField() 842 { 843 // Manual downcast. 844 return cast(gcc_jit_field *)(this.getObject()); 845 } 846 } 847 848 /// Types can be created in several ways: 849 /// $(UL 850 /// $(LI Fundamental types can be accessed using JITContext.getType()) 851 /// $(LI Derived types can be accessed by calling methods on an existing type.) 852 /// $(LI By creating structures via JITStruct.) 853 /// ) 854 855 class JITType : JITObject 856 { 857 /// 858 this() 859 { 860 super(); 861 } 862 863 /// 864 this(gcc_jit_type *type) 865 { 866 super(gcc_jit_type_as_object(type)); 867 } 868 869 /// Returns the internal gcc_jit_type object. 870 final gcc_jit_type *getType() 871 { 872 // Manual downcast. 873 return cast(gcc_jit_type *)(this.getObject()); 874 } 875 876 /// Given type T, get type T*. 877 final JITType pointerOf() 878 { 879 auto result = gcc_jit_type_get_pointer(this.getType()); 880 return new JITType(result); 881 } 882 883 /// Given type T, get type const T. 884 final JITType constOf() 885 { 886 auto result = gcc_jit_type_get_const(this.getType()); 887 return new JITType(result); 888 } 889 890 /// Given type T, get type volatile T. 891 final JITType volatileOf() 892 { 893 auto result = gcc_jit_type_get_volatile(this.getType()); 894 return new JITType(result); 895 } 896 } 897 898 /// You can model C struct types by creating JITStruct and JITField 899 /// instances, in either order: 900 /// $(UL 901 /// $(LI By creating the fields, then the structure.) 902 /// $(LI By creating the structure, then populating it with fields, 903 /// typically to allow modelling self-referential structs.) 904 /// ) 905 class JITStruct : JITType 906 { 907 /// 908 this() 909 { 910 super(null); 911 } 912 913 /// 914 this(gcc_jit_struct *agg) 915 { 916 super(gcc_jit_struct_as_type(agg)); 917 } 918 919 /// Returns the internal gcc_jit_struct object. 920 final gcc_jit_struct *getStruct() 921 { 922 // Manual downcast. 923 return cast(gcc_jit_struct *)(this.getObject()); 924 } 925 926 /// Populate the fields of a formerly-opaque struct type. 927 /// This can only be called once on a given struct type. 928 final void setFields(JITLocation loc, JITField[] fields...) 929 { 930 // Convert to an array of inner pointers. 931 gcc_jit_field*[] field_p = new gcc_jit_field*[fields.length]; 932 foreach(i, field; fields) 933 field_p[i] = field.getField(); 934 935 // Treat the array as being of the underlying pointers, relying on 936 // the wrapper type being such a pointer internally. 937 gcc_jit_struct_set_fields(this.getStruct(), loc ? loc.getLocation() : null, 938 cast(int)fields.length, field_p.ptr); 939 } 940 941 /// Ditto 942 final void setFields(JITField[] fields...) 943 { 944 this.setFields(null, fields); 945 } 946 } 947 948 /// Class wrapper for gcc_jit_function 949 class JITFunction : JITObject 950 { 951 /// 952 this() 953 { 954 super(); 955 } 956 957 /// 958 this(gcc_jit_function *func) 959 { 960 if (!func) 961 throw new JITError("Unknown error, got bad function"); 962 super(gcc_jit_function_as_object(func)); 963 } 964 965 /// Returns the internal gcc_jit_function object. 966 final gcc_jit_function *getFunction() 967 { 968 // Manual downcast. 969 return cast(gcc_jit_function *)(this.getObject()); 970 } 971 972 /// Dump function to dot file. 973 final void dump(string path) 974 { 975 gcc_jit_function_dump_to_dot(this.getFunction(), path.toStringz()); 976 } 977 978 /// Get a specific param of a function by index. 979 final JITParam getParam(int index) 980 { 981 auto result = gcc_jit_function_get_param(this.getFunction(), index); 982 return new JITParam(result); 983 } 984 985 /// Create a new JITBlock. 986 /// The name can be null, or you can give it a meaningful name, which may 987 /// show up in dumps of the internal representation, and in error messages. 988 final JITBlock newBlock() 989 { 990 auto result = gcc_jit_function_new_block(this.getFunction(), null); 991 return new JITBlock(result); 992 } 993 994 /// Ditto 995 final JITBlock newBlock(string name) 996 { 997 auto result = gcc_jit_function_new_block(this.getFunction(), 998 name.toStringz()); 999 return new JITBlock(result); 1000 } 1001 1002 /// Create a new local variable. 1003 final JITLValue newLocal(JITLocation loc, JITType type, string name) 1004 { 1005 auto result = gcc_jit_function_new_local(this.getFunction(), 1006 loc ? loc.getLocation() : null, 1007 type.getType(), 1008 name.toStringz()); 1009 return new JITLValue(result); 1010 } 1011 1012 /// Ditto 1013 final JITLValue newLocal(JITType type, string name) 1014 { 1015 return this.newLocal(null, type, name); 1016 } 1017 } 1018 1019 1020 /// Class wrapper for gcc_jit_block 1021 class JITBlock : JITObject 1022 { 1023 /// 1024 this() 1025 { 1026 super(); 1027 } 1028 1029 /// 1030 this(gcc_jit_block *block) 1031 { 1032 super(gcc_jit_block_as_object(block)); 1033 } 1034 1035 /// Returns the internal gcc_jit_block object. 1036 final gcc_jit_block *getBlock() 1037 { 1038 // Manual downcast. 1039 return cast(gcc_jit_block *)(this.getObject()); 1040 } 1041 1042 /// Returns the JITFunction this JITBlock is within. 1043 final JITFunction getFunction() 1044 { 1045 auto result = gcc_jit_block_get_function(this.getBlock()); 1046 return new JITFunction(result); 1047 } 1048 1049 /// Add evaluation of an rvalue, discarding the result. 1050 final void addEval(JITLocation loc, JITRValue rvalue) 1051 { 1052 gcc_jit_block_add_eval(this.getBlock(), 1053 loc ? loc.getLocation() : null, 1054 rvalue.getRValue()); 1055 } 1056 1057 /// Ditto 1058 final void addEval(JITRValue rvalue) 1059 { 1060 return this.addEval(null, rvalue); 1061 } 1062 1063 /// Add evaluation of an rvalue, assigning the result to the given lvalue. 1064 /// This is equivalent to "lvalue = rvalue". 1065 final void addAssignment(JITLocation loc, JITLValue lvalue, JITRValue rvalue) 1066 { 1067 gcc_jit_block_add_assignment(this.getBlock(), 1068 loc ? loc.getLocation() : null, 1069 lvalue.getLValue(), rvalue.getRValue()); 1070 } 1071 1072 /// Ditto 1073 final void addAssignment(JITLValue lvalue, JITRValue rvalue) 1074 { 1075 return this.addAssignment(null, lvalue, rvalue); 1076 } 1077 1078 /// Add evaluation of an rvalue, using the result to modify an lvalue. 1079 /// This is equivalent to "lvalue op= rvalue". 1080 final void addAssignmentOp(JITLocation loc, JITLValue lvalue, 1081 JITBinaryOp op, JITRValue rvalue) 1082 { 1083 gcc_jit_block_add_assignment_op(this.getBlock(), 1084 loc ? loc.getLocation() : null, 1085 lvalue.getLValue(), op, rvalue.getRValue()); 1086 } 1087 1088 /// Ditto 1089 final void addAssignmentOp(JITLValue lvalue, JITBinaryOp op, JITRValue rvalue) 1090 { 1091 return this.addAssignmentOp(null, lvalue, op, rvalue); 1092 } 1093 1094 /// A way to add a function call to the body of a function being 1095 /// defined, with various number of args. 1096 final JITRValue addCall(JITLocation loc, JITFunction func, JITRValue[] args...) 1097 { 1098 JITRValue rv = this.getContext().newCall(loc, func, args); 1099 this.addEval(loc, rv); 1100 return rv; 1101 } 1102 1103 /// Ditto 1104 final JITRValue addCall(JITFunction func, JITRValue[] args...) 1105 { 1106 return this.addCall(null, func, args); 1107 } 1108 1109 /// Add a no-op textual comment to the internal representation of the code. 1110 /// It will be optimized away, but visible in the dumps seens via 1111 /// JITBoolOption.DUMP_INITIAL_TREE and JITBoolOption.DUMP_INITIAL_GIMPLE. 1112 final void addComment(JITLocation loc, string text) 1113 { 1114 gcc_jit_block_add_comment(this.getBlock(), 1115 loc ? loc.getLocation() : null, 1116 text.toStringz()); 1117 } 1118 1119 /// Ditto 1120 final void addComment(string text) 1121 { 1122 return this.addComment(null, text); 1123 } 1124 1125 /// Terminate a block by adding evaluation of an rvalue, branching on the 1126 /// result to the appropriate successor block. 1127 final void endWithConditional(JITLocation loc, JITRValue val, 1128 JITBlock on_true, JITBlock on_false) 1129 { 1130 gcc_jit_block_end_with_conditional(this.getBlock(), 1131 loc ? loc.getLocation() : null, 1132 val.getRValue(), 1133 on_true.getBlock(), 1134 on_false.getBlock()); 1135 } 1136 1137 /// Ditto 1138 final void endWithConditional(JITRValue val, JITBlock on_true, JITBlock on_false) 1139 { 1140 return this.endWithConditional(null, val, on_true, on_false); 1141 } 1142 1143 /// Terminate a block by adding a jump to the given target block. 1144 /// This is equivalent to "goto target". 1145 final void endWithJump(JITLocation loc, JITBlock target) 1146 { 1147 gcc_jit_block_end_with_jump(this.getBlock(), 1148 loc ? loc.getLocation() : null, 1149 target.getBlock()); 1150 } 1151 1152 /// Ditto 1153 final void endWithJump(JITBlock target) 1154 { 1155 return this.endWithJump(null, target); 1156 } 1157 1158 /// Terminate a block by adding evaluation of an rvalue, returning the value. 1159 /// This is equivalent to "return rvalue". 1160 final void endWithReturn(JITLocation loc, JITRValue rvalue) 1161 { 1162 gcc_jit_block_end_with_return(this.getBlock(), 1163 loc ? loc.getLocation() : null, 1164 rvalue.getRValue()); 1165 } 1166 1167 /// Ditto 1168 final void endWithReturn(JITRValue rvalue) 1169 { 1170 return this.endWithReturn(null, rvalue); 1171 } 1172 1173 /// Terminate a block by adding a valueless return, for use within a 1174 /// function with "void" return type. 1175 /// This is equivalent to "return". 1176 final void endWithReturn(JITLocation loc = null) 1177 { 1178 gcc_jit_block_end_with_void_return(this.getBlock(), 1179 loc ? loc.getLocation() : null); 1180 } 1181 } 1182 1183 /// Class wrapper for gcc_jit_rvalue 1184 class JITRValue : JITObject 1185 { 1186 /// 1187 this() 1188 { 1189 super(); 1190 } 1191 1192 /// 1193 this(gcc_jit_rvalue *rvalue) 1194 { 1195 if (!rvalue) 1196 throw new JITError("Unknown error, got bad rvalue"); 1197 super(gcc_jit_rvalue_as_object(rvalue)); 1198 } 1199 1200 /// Returns the internal gcc_jit_rvalue object. 1201 final gcc_jit_rvalue *getRValue() 1202 { 1203 // Manual downcast. 1204 return cast(gcc_jit_rvalue *)(this.getObject()); 1205 } 1206 1207 /// Returns the JITType of the rvalue. 1208 final JITType getType() 1209 { 1210 auto result = gcc_jit_rvalue_get_type(this.getRValue()); 1211 return new JITType(result); 1212 } 1213 1214 /// Accessing a field of an rvalue of struct type. 1215 /// This is equivalent to "(value).field". 1216 JITRValue accessField(JITLocation loc, JITField field) 1217 { 1218 auto result = gcc_jit_rvalue_access_field(this.getRValue(), 1219 loc ? loc.getLocation() : null, 1220 field.getField()); 1221 return new JITRValue(result); 1222 } 1223 1224 /// Ditto 1225 JITRValue accessField(JITField field) 1226 { 1227 return this.accessField(null, field); 1228 } 1229 1230 /// Accessing a field of an rvalue of pointer type. 1231 /// This is equivalent to "(*value).field". 1232 final JITLValue dereferenceField(JITLocation loc, JITField field) 1233 { 1234 auto result = gcc_jit_rvalue_dereference_field(this.getRValue(), 1235 loc ? loc.getLocation() : null, 1236 field.getField()); 1237 return new JITLValue(result); 1238 } 1239 1240 /// Ditto 1241 final JITLValue dereferenceField(JITField field) 1242 { 1243 return this.dereferenceField(null, field); 1244 } 1245 1246 /// Dereferencing an rvalue of pointer type. 1247 /// This is equivalent to "*(value)". 1248 final JITLValue dereference(JITLocation loc = null) 1249 { 1250 auto result = gcc_jit_rvalue_dereference(this.getRValue(), 1251 loc ? loc.getLocation() : null); 1252 return new JITLValue(result); 1253 } 1254 1255 /// Convert an rvalue to the given JITType. See JITContext.newCast for 1256 /// limitations. 1257 final JITRValue castTo(JITLocation loc, JITType type) 1258 { 1259 return this.getContext().newCast(loc, this, type); 1260 } 1261 1262 /// Ditto 1263 final JITRValue castTo(JITType type) 1264 { 1265 return this.castTo(null, type); 1266 } 1267 1268 /// Ditto 1269 final JITRValue castTo(JITLocation loc, JITTypeKind kind) 1270 { 1271 return this.castTo(loc, this.getContext().getType(kind)); 1272 } 1273 1274 /// Ditto 1275 final JITRValue castTo(JITTypeKind kind) 1276 { 1277 return this.castTo(null, this.getContext().getType(kind)); 1278 } 1279 } 1280 1281 /// Class wrapper for gcc_jit_lvalue 1282 class JITLValue : JITRValue 1283 { 1284 /// 1285 this() 1286 { 1287 super(); 1288 } 1289 1290 /// 1291 this(gcc_jit_lvalue *lvalue) 1292 { 1293 if (!lvalue) 1294 throw new JITError("Unknown error, got bad lvalue"); 1295 super(gcc_jit_lvalue_as_rvalue(lvalue)); 1296 } 1297 1298 /// Returns the internal gcc_jit_lvalue object. 1299 final gcc_jit_lvalue *getLValue() 1300 { 1301 // Manual downcast. 1302 return cast(gcc_jit_lvalue *)(this.getObject()); 1303 } 1304 1305 /// Accessing a field of an lvalue of struct type. 1306 /// This is equivalent to "(value).field = ...". 1307 override JITLValue accessField(JITLocation loc, JITField field) 1308 { 1309 auto result = gcc_jit_lvalue_access_field(this.getLValue(), 1310 loc ? loc.getLocation() : null, 1311 field.getField()); 1312 return new JITLValue(result); 1313 } 1314 1315 /// Ditto 1316 override JITLValue accessField(JITField field) 1317 { 1318 return this.accessField(null, field); 1319 } 1320 1321 /// Taking the address of an lvalue. 1322 /// This is equivalent to "&(value)". 1323 final JITRValue getAddress(JITLocation loc = null) 1324 { 1325 auto result = gcc_jit_lvalue_get_address(this.getLValue(), 1326 loc ? loc.getLocation() : null); 1327 return new JITRValue(result); 1328 } 1329 } 1330 1331 /// Class wrapper for gcc_jit_param 1332 class JITParam : JITLValue 1333 { 1334 /// 1335 this() 1336 { 1337 super(); 1338 } 1339 1340 /// 1341 this(gcc_jit_param *param) 1342 { 1343 if (!param) 1344 throw new JITError("Unknown error, got bad param"); 1345 super(gcc_jit_param_as_lvalue(param)); 1346 } 1347 1348 /// Returns the internal gcc_jit_param object. 1349 final gcc_jit_param *getParam() 1350 { 1351 // Manual downcast. 1352 return cast(gcc_jit_param *)(this.getObject()); 1353 } 1354 } 1355 1356 /// Class wrapper for gcc_jit_result 1357 final class JITResult 1358 { 1359 /// 1360 this() 1361 { 1362 this.m_inner_result = null; 1363 } 1364 1365 /// 1366 this(gcc_jit_result *result) 1367 { 1368 if (!result) 1369 throw new JITError("Unknown error, got bad result"); 1370 this.m_inner_result = result; 1371 } 1372 1373 /// Returns the internal gcc_jit_result object. 1374 gcc_jit_result *getResult() 1375 { 1376 return this.m_inner_result; 1377 } 1378 1379 /// Locate a given function within the built machine code. 1380 /// This will need to be cast to a function pointer of the correct type 1381 /// before it can be called. 1382 void *getCode(string name) 1383 { 1384 return gcc_jit_result_get_code(this.getResult(), name.toStringz()); 1385 } 1386 1387 /// Locate a given global within the built machine code. 1388 /// It must have been created using JITGlobalKind.EXPORTED. 1389 /// This returns is a pointer to the global. 1390 void *getGlobal(string name) 1391 { 1392 return gcc_jit_result_get_global(this.getResult(), name.toStringz()); 1393 } 1394 1395 /// Once we're done with the code, this unloads the built .so file. 1396 /// After this call, it's no longer valid to use this JITResult. 1397 void release() 1398 { 1399 gcc_jit_result_release(this.getResult()); 1400 } 1401 1402 private: 1403 gcc_jit_result *m_inner_result; 1404 } 1405 1406 /// Kinds of function. 1407 enum JITFunctionKind : gcc_jit_function_kind 1408 { 1409 /// Function is defined by the client code and visible by name 1410 /// outside of the JIT. 1411 EXPORTED = GCC_JIT_FUNCTION_EXPORTED, 1412 /// Function is defined by the client code, but is invisible 1413 /// outside of the JIT. 1414 INTERNAL = GCC_JIT_FUNCTION_INTERNAL, 1415 /// Function is not defined by the client code; we're merely 1416 /// referring to it. 1417 IMPORTED = GCC_JIT_FUNCTION_IMPORTED, 1418 /// Function is only ever inlined into other functions, and is 1419 /// invisible outside of the JIT. 1420 ALWAYS_INLINE = GCC_JIT_FUNCTION_ALWAYS_INLINE, 1421 } 1422 1423 /// Kinds of global. 1424 enum JITGlobalKind : gcc_jit_global_kind 1425 { 1426 /// Global is defined by the client code and visible by name 1427 /// outside of this JIT context. 1428 EXPORTED = GCC_JIT_GLOBAL_EXPORTED, 1429 /// Global is defined by the client code, but is invisible 1430 /// outside of this JIT context. Analogous to a "static" global. 1431 INTERNAL = GCC_JIT_GLOBAL_INTERNAL, 1432 /// Global is not defined by the client code; we're merely 1433 /// referring to it. Analogous to using an "extern" global. 1434 IMPORTED = GCC_JIT_GLOBAL_IMPORTED, 1435 } 1436 1437 /// Standard types. 1438 enum JITTypeKind : gcc_jit_types 1439 { 1440 /// C's void type. 1441 VOID = GCC_JIT_TYPE_VOID, 1442 1443 /// C's void* type. 1444 VOID_PTR = GCC_JIT_TYPE_VOID_PTR, 1445 1446 /// C++'s bool type. 1447 BOOL = GCC_JIT_TYPE_BOOL, 1448 1449 /// C's char type. 1450 CHAR = GCC_JIT_TYPE_CHAR, 1451 1452 /// C's signed char type. 1453 SIGNED_CHAR = GCC_JIT_TYPE_SIGNED_CHAR, 1454 1455 /// C's unsigned char type. 1456 UNSIGNED_CHAR = GCC_JIT_TYPE_UNSIGNED_CHAR, 1457 1458 /// C's short type. 1459 SHORT = GCC_JIT_TYPE_SHORT, 1460 1461 /// C's unsigned short type. 1462 UNSIGNED_SHORT = GCC_JIT_TYPE_UNSIGNED_SHORT, 1463 1464 /// C's int type. 1465 INT = GCC_JIT_TYPE_INT, 1466 1467 /// C's unsigned int type. 1468 UNSIGNED_INT = GCC_JIT_TYPE_UNSIGNED_INT, 1469 1470 /// C's long type. 1471 LONG = GCC_JIT_TYPE_LONG, 1472 1473 /// C's unsigned long type. 1474 UNSIGNED_LONG = GCC_JIT_TYPE_UNSIGNED_LONG, 1475 1476 /// C99's long long type. 1477 LONG_LONG = GCC_JIT_TYPE_LONG_LONG, 1478 1479 /// C99's unsigned long long type. 1480 UNSIGNED_LONG_LONG = GCC_JIT_TYPE_UNSIGNED_LONG_LONG, 1481 1482 /// Single precision floating point type. 1483 FLOAT = GCC_JIT_TYPE_FLOAT, 1484 1485 /// Double precision floating point type. 1486 DOUBLE = GCC_JIT_TYPE_DOUBLE, 1487 1488 /// Largest supported floating point type. 1489 LONG_DOUBLE = GCC_JIT_TYPE_LONG_DOUBLE, 1490 1491 /// C's const char* type. 1492 CONST_CHAR_PTR = GCC_JIT_TYPE_CONST_CHAR_PTR, 1493 1494 /// C's size_t type. 1495 SIZE_T = GCC_JIT_TYPE_SIZE_T, 1496 1497 /// C's FILE* type. 1498 FILE_PTR = GCC_JIT_TYPE_FILE_PTR, 1499 1500 /// Single precision complex float type. 1501 COMPLEX_FLOAT = GCC_JIT_TYPE_COMPLEX_FLOAT, 1502 1503 /// Double precision complex float type. 1504 COMPLEX_DOUBLE = GCC_JIT_TYPE_COMPLEX_DOUBLE, 1505 1506 /// Largest supported complex float type. 1507 COMPLEX_LONG_DOUBLE = GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE, 1508 } 1509 1510 /// Kinds of unary ops. 1511 enum JITUnaryOp : gcc_jit_unary_op 1512 { 1513 /// Negate an arithmetic value. 1514 /// This is equivalent to "-(value)". 1515 MINUS = GCC_JIT_UNARY_OP_MINUS, 1516 /// Bitwise negation of an integer value (one's complement). 1517 /// This is equivalent to "~(value)". 1518 BITWISE_NEGATE = GCC_JIT_UNARY_OP_BITWISE_NEGATE, 1519 /// Logical negation of an arithmetic or pointer value. 1520 /// This is equivalent to "!(value)". 1521 LOGICAL_NEGATE = GCC_JIT_UNARY_OP_LOGICAL_NEGATE, 1522 } 1523 1524 /// Kinds of binary ops. 1525 enum JITBinaryOp : gcc_jit_binary_op 1526 { 1527 /// Addition of arithmetic values. 1528 /// This is equivalent to "(a) + (b)". 1529 PLUS = GCC_JIT_BINARY_OP_PLUS, 1530 /// Subtraction of arithmetic values. 1531 /// This is equivalent to "(a) - (b)". 1532 MINUS = GCC_JIT_BINARY_OP_MINUS, 1533 /// Multiplication of a pair of arithmetic values. 1534 /// This is equivalent to "(a) * (b)". 1535 MULT = GCC_JIT_BINARY_OP_MULT, 1536 /// Quotient of division of arithmetic values. 1537 /// This is equivalent to "(a) / (b)". 1538 DIVIDE = GCC_JIT_BINARY_OP_DIVIDE, 1539 /// Remainder of division of arithmetic values. 1540 /// This is equivalent to "(a) % (b)". 1541 MODULO = GCC_JIT_BINARY_OP_MODULO, 1542 /// Bitwise AND. 1543 /// This is equivalent to "(a) & (b)". 1544 BITWISE_AND = GCC_JIT_BINARY_OP_BITWISE_AND, 1545 /// Bitwise exclusive OR. 1546 /// This is equivalent to "(a) ^ (b)". 1547 BITWISE_XOR = GCC_JIT_BINARY_OP_BITWISE_XOR, 1548 /// Bitwise inclusive OR. 1549 /// This is equivalent to "(a) | (b)". 1550 BITWISE_OR = GCC_JIT_BINARY_OP_BITWISE_OR, 1551 /// Logical AND. 1552 /// This is equivalent to "(a) && (b)". 1553 LOGICAL_AND = GCC_JIT_BINARY_OP_LOGICAL_AND, 1554 /// Logical OR. 1555 /// This is equivalent to "(a) || (b)". 1556 LOGICAL_OR = GCC_JIT_BINARY_OP_LOGICAL_OR, 1557 /// Left shift. 1558 /// This is equivalent to "(a) << (b)". 1559 LSHIFT = GCC_JIT_BINARY_OP_LSHIFT, 1560 /// Right shift. 1561 /// This is equivalent to "(a) >> (b)". 1562 RSHIFT = GCC_JIT_BINARY_OP_RSHIFT, 1563 } 1564 1565 /// Kinds of comparison. 1566 enum JITComparison : gcc_jit_comparison 1567 { 1568 /// This is equivalent to "(a) == (b)". 1569 EQ = GCC_JIT_COMPARISON_EQ, 1570 /// This is equivalent to "(a) != (b)". 1571 NE = GCC_JIT_COMPARISON_NE, 1572 /// This is equivalent to "(a) < (b)". 1573 LT = GCC_JIT_COMPARISON_LT, 1574 /// This is equivalent to "(a) <= (b)". 1575 LE = GCC_JIT_COMPARISON_LE, 1576 /// This is equivalent to "(a) > (b)". 1577 GT = GCC_JIT_COMPARISON_GT, 1578 /// This is equivalent to "(a) >= (b)". 1579 GE = GCC_JIT_COMPARISON_GE, 1580 } 1581 1582 /// String options 1583 enum JITStrOption : gcc_jit_str_option 1584 { 1585 /// The name of the program, for use as a prefix when printing error 1586 /// messages to stderr. If None, or default, "libgccjit.so" is used. 1587 PROGNAME = GCC_JIT_STR_OPTION_PROGNAME, 1588 } 1589 1590 /// Integer options 1591 enum JITIntOption : gcc_jit_int_option 1592 { 1593 /// How much to optimize the code. 1594 1595 /// Valid values are 0-3, corresponding to GCC's command-line options 1596 /// -O0 through -O3. 1597 1598 /// The default value is 0 (unoptimized). 1599 OPTIMIZATION_LEVEL = GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL, 1600 } 1601 1602 /// Boolean options 1603 enum JITBoolOption : gcc_jit_bool_option 1604 { 1605 /// If true, JITContext.compile() will attempt to do the right thing 1606 /// so that if you attach a debugger to the process, it will be able 1607 /// to inspect variables and step through your code. 1608 1609 /// Note that you can’t step through code unless you set up source 1610 /// location information for the code (by creating and passing in 1611 /// JITLocation instances). 1612 DEBUGINFO = GCC_JIT_BOOL_OPTION_DEBUGINFO, 1613 1614 /// If true, JITContext.compile() will dump its initial "tree" 1615 /// representation of your code to stderr, before any optimizations. 1616 DUMP_INITIAL_TREE = GCC_JIT_BOOL_OPTION_DUMP_INITIAL_TREE, 1617 1618 /// If true, JITContext.compile() will dump its initial "gimple" 1619 /// representation of your code to stderr, before any optimizations 1620 /// are performed. The dump resembles C code. 1621 DUMP_INITIAL_GIMPLE = GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE, 1622 1623 /// If true, JITContext.compile() will dump the final generated code 1624 /// to stderr, in the form of assembly language. 1625 DUMP_GENERATED_CODE = GCC_JIT_BOOL_OPTION_DUMP_GENERATED_CODE, 1626 1627 /// If true, JITContext.compile() will print information to stderr 1628 /// on the actions it is performing, followed by a profile showing 1629 /// the time taken and memory usage of each phase. 1630 DUMP_SUMMARY = GCC_JIT_BOOL_OPTION_DUMP_SUMMARY, 1631 1632 /// If true, JITContext.compile() will dump copious amounts of 1633 /// information on what it’s doing to various files within a 1634 /// temporary directory. Use JITBoolOption.KEEP_INTERMEDIATES 1635 /// to see the results. The files are intended to be human-readable, 1636 /// but the exact files and their formats are subject to change. 1637 DUMP_EVERYTHING = GCC_JIT_BOOL_OPTION_DUMP_EVERYTHING, 1638 1639 /// If true, libgccjit will aggressively run its garbage collector, 1640 /// to shake out bugs (greatly slowing down the compile). This is 1641 /// likely to only be of interest to developers of the library. 1642 SELFCHECK_GC = GCC_JIT_BOOL_OPTION_SELFCHECK_GC, 1643 1644 /// If true, the JITContext will not clean up intermediate files 1645 /// written to the filesystem, and will display their location on 1646 /// stderr. 1647 KEEP_INTERMEDIATES = GCC_JIT_BOOL_OPTION_KEEP_INTERMEDIATES, 1648 } 1649