egeditor: more VaVoom C highlighting
[iv.d.git] / gccjit.d
blob5f8c0821f78d55e9fd8656316b6d3e30263a4666
1 /// A D API for libgccjit, purely as final class wrapper functions.
2 /// Copyright (C) 2014-2015 Iain Buclaw.
4 /// This file is part of gccjitd.
6 /// This program is free software: you can redistribute it and/or modify
7 /// it under the terms of the GNU General Public License as published by
8 /// the Free Software Foundation, either version 3 of the License, or
9 /// (at your option) any later version.
11 /// This program is distributed in the hope that it will be useful,
12 /// but WITHOUT ANY WARRANTY; without even the implied warranty of
13 /// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 /// GNU General Public License for more details.
16 /// You should have received a copy of the GNU General Public License
17 /// along with this program. If not, see <http://www.gnu.org/licenses/>.
18 module iv.gccjit /*is aliced*/;
19 pragma(lib, "gccjit");
21 import iv.alice;
22 import std.conv : to;
23 import std.string : toStringz;
24 import std.traits : isIntegral, isSigned;
26 /// Errors within the API become D exceptions of this class.
27 final class JITError : Exception
29 @safe pure nothrow this(string msg, Throwable next = null)
31 super(msg, next);
34 @safe pure nothrow this(string msg, string file, usize line, Throwable next = null)
36 super(msg, file, line, next);
40 /// Class wrapper for gcc_jit_object.
41 /// All JITObject's are created within a JITContext, and are automatically
42 /// cleaned up when the context is released.
44 /// The class hierachy looks like this:
45 /// $(OL - JITObject
46 /// $(OL - JITLocation)
47 /// $(OL - JITType
48 /// $(OL - JITStruct))
49 /// $(OL - JITField)
50 /// $(OL - JITFunction)
51 /// $(OL - JITBlock)
52 /// $(OL - JITRValue
53 /// $(OL - JITLValue
54 /// $(OL - JITParam))))
55 class JITObject
57 /// Return the context this JITObject is within.
58 final JITContext getContext()
60 auto result = gcc_jit_object_get_context(this.m_inner_obj);
61 return new JITContext(result);
64 /// Get a human-readable description of this object.
65 override final string toString()
67 auto result = gcc_jit_object_get_debug_string(this.m_inner_obj);
68 return to!string(result);
71 protected:
72 // Constructors and getObject are hidden from public.
73 this()
75 this.m_inner_obj = null;
78 this(gcc_jit_object *obj)
80 if (!obj)
81 throw new JITError("Unknown error, got bad object");
82 this.m_inner_obj = obj;
85 final gcc_jit_object *getObject()
87 return this.m_inner_obj;
90 private:
91 // The actual gccjit object we interface with.
92 gcc_jit_object *m_inner_obj;
95 /// Class wrapper for gcc_jit_location.
96 /// A JITLocation encapsulates a source code locations, so that you can associate
97 /// locations in your language with statements in the JIT-compiled code.
98 class JITLocation : JITObject
101 this()
103 super();
107 this(gcc_jit_location *loc)
109 super(gcc_jit_location_as_object(loc));
112 /// Returns the internal gcc_jit_location object.
113 final gcc_jit_location *getLocation()
115 // Manual downcast.
116 return cast(gcc_jit_location *)(this.getObject());
120 /// The top-level of the API is the JITContext class.
122 /// A JITContext instance encapsulates the state of a compilation.
123 /// It goes through two states.
124 /// Initial:
125 /// During which you can set up options on it, and add types,
126 /// functions and code, using the API below. Invoking compile
127 /// on it transitions it to the PostCompilation state.
128 /// PostCompilation:
129 /// When you can call JITContext.release to clean it up.
130 final class JITContext
133 this(bool acquire = true)
135 if (acquire)
136 this.m_inner_ctxt = gcc_jit_context_acquire();
137 else
138 this.m_inner_ctxt = null;
142 this(gcc_jit_context *context)
144 if (!context)
145 throw new JITError("Unknown error, got bad context");
146 this.m_inner_ctxt = context;
149 /// Acquire a JIT-compilation context.
150 static JITContext acquire()
152 return new JITContext(gcc_jit_context_acquire());
155 /// Release the context.
156 /// After this call, it's no longer valid to use this JITContext.
157 void release()
159 gcc_jit_context_release(this.m_inner_ctxt);
160 this.m_inner_ctxt = null;
163 /// Set a string option of the context; see JITStrOption for notes
164 /// on the options and their meanings.
165 /// Params:
166 /// opt = Which option to set.
167 /// value = The new value.
168 void setOption(JITStrOption opt, string value)
170 gcc_jit_context_set_str_option(this.m_inner_ctxt, opt, value.toStringz());
173 /// Set an integer option of the context; see JITIntOption for notes
174 /// on the options and their meanings.
175 /// Params:
176 /// opt = Which option to set.
177 /// value = The new value.
178 void setOption(JITIntOption opt, int value)
180 gcc_jit_context_set_int_option(this.m_inner_ctxt, opt, value);
183 /// Set a boolean option of the context; see JITBoolOption for notes
184 /// on the options and their meanings.
185 /// Params:
186 /// opt = Which option to set.
187 /// value = The new value.
188 void setOption(JITBoolOption opt, bool value)
190 gcc_jit_context_set_bool_option(this.m_inner_ctxt, opt, value);
193 /// Calls into GCC and runs the build. It can only be called once on a
194 /// given context.
195 /// Returns:
196 /// A wrapper around a .so file.
197 JITResult compile()
199 auto result = gcc_jit_context_compile(this.m_inner_ctxt);
200 if (!result)
201 throw new JITError(this.getFirstError());
202 return new JITResult(result);
205 /// Returns:
206 /// The first error message that occurred when compiling the context.
207 string getFirstError()
209 const char *err = gcc_jit_context_get_first_error(this.m_inner_ctxt);
210 if (err)
211 return to!string(err);
212 return null;
215 /// Dump a C-like representation describing what's been set up on the
216 /// context to file.
217 /// Params:
218 /// path = Location of file to write to.
219 /// update_locations = If true, then also write JITLocation information.
220 void dump(string path, bool update_locations)
222 gcc_jit_context_dump_to_file(this.m_inner_ctxt,
223 path.toStringz(),
224 update_locations);
227 /// Returns the internal gcc_jit_context object.
228 gcc_jit_context *getContext()
230 return this.m_inner_ctxt;
233 /// Build a JITType from one of the types in JITTypeKind.
234 JITType getType(JITTypeKind kind)
236 auto result = gcc_jit_context_get_type(this.m_inner_ctxt, kind);
237 return new JITType(result);
240 /// Build an integer type of a given size and signedness.
241 JITType getIntType(int num_bytes, bool is_signed)
243 auto result = gcc_jit_context_get_int_type(this.m_inner_ctxt,
244 num_bytes, is_signed);
245 return new JITType(result);
248 /// A way to map a specific int type, using the compiler to
249 /// get the details automatically e.g:
250 /// JITType type = getIntType!usize();
251 JITType getIntType(T)() if (isIntegral!T)
253 return this.getIntType(T.sizeof, isSigned!T);
256 /// Create a reference to a GCC builtin function.
257 JITFunction getBuiltinFunction(string name)
259 auto result = gcc_jit_context_get_builtin_function(this.m_inner_ctxt,
260 name.toStringz());
261 return new JITFunction(result);
264 /// Create a new child context of the given JITContext, inheriting a copy
265 /// of all option settings from the parent.
266 /// The returned JITContext can reference objects created within the
267 /// parent, but not vice-versa. The lifetime of the child context must be
268 /// bounded by that of the parent. You should release a child context
269 /// before releasing the parent context.
270 JITContext newChildContext()
272 auto result = gcc_jit_context_new_child_context(this.m_inner_ctxt);
273 if (!result)
274 throw new JITError("Unknown error creating child context");
275 return new JITContext(result);
278 /// Make a JITLocation representing a source location,
279 /// for use by the debugger.
280 /// Note:
281 /// You need to enable JITBoolOption.DEBUGINFO on the context
282 /// for these locations to actually be usable by the debugger.
283 JITLocation newLocation(string filename, int line, int column)
285 auto result = gcc_jit_context_new_location(this.m_inner_ctxt,
286 filename.toStringz(),
287 line, column);
288 return new JITLocation(result);
291 /// Given type "T", build a new array type of "T[N]".
292 JITType newArrayType(JITLocation loc, JITType type, int dims)
294 auto result = gcc_jit_context_new_array_type(this.m_inner_ctxt,
295 loc ? loc.getLocation() : null,
296 type.getType(), dims);
297 return new JITType(result);
300 /// Ditto
301 JITType newArrayType(JITType type, int dims)
303 return this.newArrayType(null, type, dims);
306 /// Ditto
307 JITType newArrayType(JITLocation loc, JITTypeKind kind, int dims)
309 return this.newArrayType(loc, this.getType(kind), dims);
312 /// Ditto
313 JITType newArrayType(JITTypeKind kind, int dims)
315 return this.newArrayType(null, this.getType(kind), dims);
318 /// Create a field, for use within a struct or union.
319 JITField newField(JITLocation loc, JITType type, string name)
321 auto result = gcc_jit_context_new_field(this.m_inner_ctxt,
322 loc ? loc.getLocation() : null,
323 type.getType(),
324 name.toStringz());
325 return new JITField(result);
328 /// Ditto
329 JITField newField(JITType type, string name)
331 return this.newField(null, type, name);
334 /// Ditto
335 JITField newField(JITLocation loc, JITTypeKind kind, string name)
337 return this.newField(loc, this.getType(kind), name);
340 /// Ditto
341 JITField newField(JITTypeKind kind, string name)
343 return this.newField(null, this.getType(kind), name);
346 /// Create a struct type from an array of fields.
347 JITStruct newStructType(JITLocation loc, string name, JITField[] fields...)
349 // Convert to an array of inner pointers.
350 gcc_jit_field*[] field_p = new gcc_jit_field*[fields.length];
351 foreach(i, field; fields)
352 field_p[i] = field.getField();
354 // Treat the array as being of the underlying pointers, relying on
355 // the wrapper type being such a pointer internally.
356 auto result = gcc_jit_context_new_struct_type(this.m_inner_ctxt,
357 loc ? loc.getLocation() : null,
358 name.toStringz(),
359 cast(int)fields.length,
360 field_p.ptr);
361 return new JITStruct(result);
364 /// Ditto
365 JITStruct newStructType(string name, JITField[] fields...)
367 return this.newStructType(null, name, fields);
370 /// Create an opaque struct type.
371 JITStruct newOpaqueStructType(JITLocation loc, string name)
373 auto result = gcc_jit_context_new_opaque_struct(this.m_inner_ctxt,
374 loc ? loc.getLocation() : null,
375 name.toStringz());
376 return new JITStruct(result);
379 /// Ditto
380 JITStruct newOpaqueStructType(string name)
382 return this.newOpaqueStructType(null, name);
385 /// Create a union type from an array of fields.
386 JITType newUnionType(JITLocation loc, string name, JITField[] fields...)
388 // Convert to an array of inner pointers.
389 gcc_jit_field*[] field_p = new gcc_jit_field*[fields.length];
390 foreach(i, field; fields)
391 field_p[i] = field.getField();
393 // Treat the array as being of the underlying pointers, relying on
394 // the wrapper type being such a pointer internally.
395 auto result = gcc_jit_context_new_union_type(this.m_inner_ctxt,
396 loc ? loc.getLocation() : null,
397 name.toStringz(),
398 cast(int)fields.length,
399 field_p.ptr);
400 return new JITType(result);
403 /// Ditto
404 JITType newUnionType(string name, JITField[] fields...)
406 return this.newUnionType(null, name, fields);
409 /// Create a function type.
410 JITType newFunctionType(JITLocation loc, JITType return_type,
411 bool is_variadic, JITType[] param_types...)
413 // Convert to an array of inner pointers.
414 gcc_jit_type*[] type_p = new gcc_jit_type*[param_types.length];
415 foreach(i, type; param_types)
416 type_p[i] = type.getType();
418 // Treat the array as being of the underlying pointers, relying on
419 // the wrapper type being such a pointer internally.
420 auto result = gcc_jit_context_new_function_ptr_type(this.m_inner_ctxt,
421 loc ? loc.getLocation() : null,
422 return_type.getType(),
423 cast(int)param_types.length,
424 type_p.ptr, is_variadic);
425 return new JITType(result);
428 /// Ditto
429 JITType newFunctionType(JITType return_type, bool is_variadic,
430 JITType[] param_types...)
432 return this.newFunctionType(null, return_type, is_variadic,
433 param_types);
436 /// Ditto
437 JITType newFunctionType(JITLocation loc, JITTypeKind return_kind,
438 bool is_variadic, JITType[] param_types...)
440 return this.newFunctionType(loc, this.getType(return_kind),
441 is_variadic, param_types);
444 /// Ditto
445 JITType newFunctionType(JITTypeKind return_kind, bool is_variadic,
446 JITType[] param_types...)
448 return this.newFunctionType(null, this.getType(return_kind),
449 is_variadic, param_types);
452 /// Create a function parameter.
453 JITParam newParam(JITLocation loc, JITType type, string name)
455 auto result = gcc_jit_context_new_param(this.m_inner_ctxt,
456 loc ? loc.getLocation() : null,
457 type.getType(),
458 name.toStringz());
459 return new JITParam(result);
462 /// Ditto
463 JITParam newParam(JITType type, string name)
465 return this.newParam(null, type, name);
468 /// Ditto
469 JITParam newParam(JITLocation loc, JITTypeKind kind, string name)
471 return this.newParam(loc, this.getType(kind), name);
474 /// Ditto
475 JITParam newParam(JITTypeKind kind, string name)
477 return this.newParam(null, this.getType(kind), name);
480 /// Create a function.
481 JITFunction newFunction(JITLocation loc, JITFunctionKind kind, JITType return_type,
482 string name, bool is_variadic, JITParam[] params...)
484 // Convert to an array of inner pointers.
485 gcc_jit_param*[] param_p = new gcc_jit_param*[params.length];
486 foreach(i, param; params)
487 param_p[i] = param.getParam();
489 // Treat the array as being of the underlying pointers, relying on
490 // the wrapper type being such a pointer internally.
491 auto result = gcc_jit_context_new_function(this.m_inner_ctxt,
492 loc ? loc.getLocation() : null,
493 kind, return_type.getType(),
494 name.toStringz(),
495 cast(int)params.length,
496 param_p.ptr, is_variadic);
497 return new JITFunction(result);
500 /// Ditto
501 JITFunction newFunction(JITFunctionKind kind, JITType return_type,
502 string name, bool is_variadic, JITParam[] params...)
504 return this.newFunction(null, kind, return_type, name, is_variadic, params);
507 /// Ditto
508 JITFunction newFunction(JITLocation loc, JITFunctionKind kind, JITTypeKind return_kind,
509 string name, bool is_variadic, JITParam[] params...)
511 return this.newFunction(loc, kind, this.getType(return_kind),
512 name, is_variadic, params);
515 /// Ditto
516 JITFunction newFunction(JITFunctionKind kind, JITTypeKind return_kind,
517 string name, bool is_variadic, JITParam[] params...)
519 return this.newFunction(null, kind, this.getType(return_kind),
520 name, is_variadic, params);
524 JITLValue newGlobal(JITLocation loc, JITGlobalKind global_kind,
525 JITType type, string name)
527 auto result = gcc_jit_context_new_global(this.m_inner_ctxt,
528 loc ? loc.getLocation() : null,
529 global_kind, type.getType(),
530 name.toStringz());
531 return new JITLValue(result);
534 /// Ditto
535 JITLValue newGlobal(JITGlobalKind global_kind, JITType type, string name)
537 return this.newGlobal(null, global_kind, type, name);
540 /// Ditto
541 JITLValue newGlobal(JITLocation loc, JITGlobalKind global_kind,
542 JITTypeKind kind, string name)
544 return this.newGlobal(loc, global_kind, this.getType(kind), name);
547 /// Ditto
548 JITLValue newGlobal(JITGlobalKind global_kind, JITTypeKind kind, string name)
550 return this.newGlobal(null, global_kind, this.getType(kind), name);
553 /// Given a JITType, which must be a numeric type, get an integer constant
554 /// as a JITRValue of that type.
555 JITRValue newRValue(JITType type, int value)
557 auto result = gcc_jit_context_new_rvalue_from_int(this.m_inner_ctxt,
558 type.getType(), value);
559 return new JITRValue(result);
562 /// Ditto
563 JITRValue newRValue(JITTypeKind kind, int value)
565 return newRValue(this.getType(kind), value);
568 /// Given a JITType, which must be a floating point type, get a floating
569 /// point constant as a JITRValue of that type.
570 JITRValue newRValue(JITType type, double value)
572 auto result = gcc_jit_context_new_rvalue_from_double(this.m_inner_ctxt,
573 type.getType(), value);
574 return new JITRValue(result);
577 /// Ditto
578 JITRValue newRValue(JITTypeKind kind, double value)
580 return newRValue(this.getType(kind), value);
583 /// Given a JITType, which must be a pointer type, and an address, get a
584 /// JITRValue representing that address as a pointer of that type.
585 JITRValue newRValue(JITType type, void *value)
587 auto result = gcc_jit_context_new_rvalue_from_ptr(this.m_inner_ctxt,
588 type.getType(), value);
589 return new JITRValue(result);
592 /// Ditto
593 JITRValue newRValue(JITTypeKind kind, void *value)
595 return newRValue(this.getType(kind), value);
598 /// Make a JITRValue for the given string literal value.
599 /// Params:
600 /// value = The string literal.
601 JITRValue newRValue(string value)
603 auto result = gcc_jit_context_new_string_literal(this.m_inner_ctxt,
604 value.toStringz());
605 return new JITRValue(result);
608 /// Given a JITType, which must be a numeric type, get the constant 0 as a
609 /// JITRValue of that type.
610 JITRValue zero(JITType type)
612 auto result = gcc_jit_context_zero(this.m_inner_ctxt, type.getType());
613 return new JITRValue(result);
616 /// Ditto
617 JITRValue zero(JITTypeKind kind)
619 return this.zero(this.getType(kind));
622 /// Given a JITType, which must be a numeric type, get the constant 1 as a
623 /// JITRValue of that type.
624 JITRValue one(JITType type)
626 auto result = gcc_jit_context_one(this.m_inner_ctxt, type.getType());
627 return new JITRValue(result);
630 /// Ditto
631 JITRValue one(JITTypeKind kind)
633 return this.one(this.getType(kind));
636 /// Given a JITType, which must be a pointer type, get a JITRValue
637 /// representing the NULL pointer of that type.
638 JITRValue nil(JITType type)
640 auto result = gcc_jit_context_null(this.m_inner_ctxt, type.getType());
641 return new JITRValue(result);
644 /// Ditto
645 JITRValue nil(JITTypeKind kind)
647 return this.nil(this.getType(kind));
650 /// Generic unary operations.
652 /// Make a JITRValue for the given unary operation.
653 /// Params:
654 /// loc = The source location, if any.
655 /// op = Which unary operation.
656 /// type = The type of the result.
657 /// a = The input expression.
658 JITRValue newUnaryOp(JITLocation loc, JITUnaryOp op, JITType type, JITRValue a)
660 auto result = gcc_jit_context_new_unary_op(this.m_inner_ctxt,
661 loc ? loc.getLocation() : null,
662 op, type.getType(),
663 a.getRValue());
664 return new JITRValue(result);
667 /// Ditto
668 JITRValue newUnaryOp(JITUnaryOp op, JITType type, JITRValue a)
670 return this.newUnaryOp(null, op, type, a);
673 /// Generic binary operations.
675 /// Make a JITRValue for the given binary operation.
676 /// Params:
677 /// loc = The source location, if any.
678 /// op = Which binary operation.
679 /// type = The type of the result.
680 /// a = The first input expression.
681 /// b = The second input expression.
682 JITRValue newBinaryOp(JITLocation loc, JITBinaryOp op,
683 JITType type, JITRValue a, JITRValue b)
685 auto result = gcc_jit_context_new_binary_op(this.m_inner_ctxt,
686 loc ? loc.getLocation() : null,
687 op, type.getType(),
688 a.getRValue(),
689 b.getRValue());
690 return new JITRValue(result);
693 /// Ditto
694 JITRValue newBinaryOp(JITBinaryOp op, JITType type, JITRValue a, JITRValue b)
696 return this.newBinaryOp(null, op, type, a, b);
699 /// Generic comparisons.
701 /// Make a JITRValue of boolean type for the given comparison.
702 /// Params:
703 /// loc = The source location, if any.
704 /// op = Which comparison.
705 /// a = The first input expression.
706 /// b = The second input expression.
707 JITRValue newComparison(JITLocation loc, JITComparison op,
708 JITRValue a, JITRValue b)
710 auto result = gcc_jit_context_new_comparison(this.m_inner_ctxt,
711 loc ? loc.getLocation() : null,
712 op, a.getRValue(),
713 b.getRValue());
714 return new JITRValue(result);
717 /// Ditto
718 JITRValue newComparison(JITComparison op, JITRValue a, JITRValue b)
720 return this.newComparison(null, op, a, b);
723 /// The most general way of creating a function call.
724 JITRValue newCall(JITLocation loc, JITFunction func, JITRValue[] args...)
726 // Convert to an array of inner pointers.
727 gcc_jit_rvalue*[] arg_p = new gcc_jit_rvalue*[args.length];
728 foreach(i, arg; args)
729 arg_p[i] = arg.getRValue();
731 // Treat the array as being of the underlying pointers, relying on
732 // the wrapper type being such a pointer internally.
733 auto result = gcc_jit_context_new_call(this.m_inner_ctxt,
734 loc ? loc.getLocation() : null,
735 func.getFunction(),
736 cast(int)args.length,
737 arg_p.ptr);
738 return new JITRValue(result);
741 /// Ditto
742 JITRValue newCall(JITFunction func, JITRValue[] args...)
744 return this.newCall(null, func, args);
747 /// Calling a function through a pointer.
748 JITRValue newCall(JITLocation loc, JITRValue ptr, JITRValue[] args...)
750 // Convert to an array of inner pointers.
751 gcc_jit_rvalue*[] arg_p = new gcc_jit_rvalue*[args.length];
752 foreach(i, arg; args)
753 arg_p[i] = arg.getRValue();
755 // Treat the array as being of the underlying pointers, relying on
756 // the wrapper type being such a pointer internally.
757 auto result = gcc_jit_context_new_call_through_ptr(this.m_inner_ctxt,
758 loc ? loc.getLocation() : null,
759 ptr.getRValue(),
760 cast(int)args.length,
761 arg_p.ptr);
762 return new JITRValue(result);
765 /// Ditto
766 JITRValue newCall(JITRValue ptr, JITRValue[] args...)
768 return this.newCall(null, ptr, args);
771 /// Type-coercion.
772 /// Currently only a limited set of conversions are possible.
773 /// int <=> float and int <=> bool.
774 JITRValue newCast(JITLocation loc, JITRValue expr, JITType type)
776 auto result = gcc_jit_context_new_cast(this.m_inner_ctxt,
777 loc ? loc.getLocation() : null,
778 expr.getRValue(), type.getType());
779 return new JITRValue(result);
782 /// Ditto
783 JITRValue newCast(JITRValue expr, JITType type)
785 return this.newCast(null, expr, type);
788 /// Ditto
789 JITRValue newCast(JITLocation loc, JITRValue expr, JITTypeKind kind)
791 return this.newCast(loc, expr, this.getType(kind));
794 /// Ditto
795 JITRValue newCast(JITRValue expr, JITTypeKind kind)
797 return this.newCast(null, expr, this.getType(kind));
800 /// Accessing an array or pointer through an index.
801 /// Params:
802 /// loc = The source location, if any.
803 /// ptr = The pointer or array.
804 /// index = The index within the array.
805 JITLValue newArrayAccess(JITLocation loc, JITRValue ptr, JITRValue index)
807 auto result = gcc_jit_context_new_array_access(this.m_inner_ctxt,
808 loc ? loc.getLocation() : null,
809 ptr.getRValue(), index.getRValue());
810 return new JITLValue(result);
813 /// Ditto
814 JITLValue newArrayAccess(JITRValue ptr, JITRValue index)
816 return this.newArrayAccess(null, ptr, index);
819 private:
820 gcc_jit_context *m_inner_ctxt;
823 /// Class wrapper for gcc_jit_field
824 class JITField : JITObject
827 this()
829 super();
833 this(gcc_jit_field *field)
835 super(gcc_jit_field_as_object(field));
838 /// Returns the internal gcc_jit_field object.
839 final gcc_jit_field *getField()
841 // Manual downcast.
842 return cast(gcc_jit_field *)(this.getObject());
846 /// Types can be created in several ways:
847 /// $(UL
848 /// $(LI Fundamental types can be accessed using JITContext.getType())
849 /// $(LI Derived types can be accessed by calling methods on an existing type.)
850 /// $(LI By creating structures via JITStruct.)
851 /// )
853 class JITType : JITObject
856 this()
858 super();
862 this(gcc_jit_type *type)
864 super(gcc_jit_type_as_object(type));
867 /// Returns the internal gcc_jit_type object.
868 final gcc_jit_type *getType()
870 // Manual downcast.
871 return cast(gcc_jit_type *)(this.getObject());
874 /// Given type T, get type T*.
875 final JITType pointerOf()
877 auto result = gcc_jit_type_get_pointer(this.getType());
878 return new JITType(result);
881 /// Given type T, get type const T.
882 final JITType constOf()
884 auto result = gcc_jit_type_get_const(this.getType());
885 return new JITType(result);
888 /// Given type T, get type volatile T.
889 final JITType volatileOf()
891 auto result = gcc_jit_type_get_volatile(this.getType());
892 return new JITType(result);
896 /// You can model C struct types by creating JITStruct and JITField
897 /// instances, in either order:
898 /// $(UL
899 /// $(LI By creating the fields, then the structure.)
900 /// $(LI By creating the structure, then populating it with fields,
901 /// typically to allow modelling self-referential structs.)
902 /// )
903 class JITStruct : JITType
906 this()
908 super(null);
912 this(gcc_jit_struct *agg)
914 super(gcc_jit_struct_as_type(agg));
917 /// Returns the internal gcc_jit_struct object.
918 final gcc_jit_struct *getStruct()
920 // Manual downcast.
921 return cast(gcc_jit_struct *)(this.getObject());
924 /// Populate the fields of a formerly-opaque struct type.
925 /// This can only be called once on a given struct type.
926 final void setFields(JITLocation loc, JITField[] fields...)
928 // Convert to an array of inner pointers.
929 gcc_jit_field*[] field_p = new gcc_jit_field*[fields.length];
930 foreach(i, field; fields)
931 field_p[i] = field.getField();
933 // Treat the array as being of the underlying pointers, relying on
934 // the wrapper type being such a pointer internally.
935 gcc_jit_struct_set_fields(this.getStruct(), loc ? loc.getLocation() : null,
936 cast(int)fields.length, field_p.ptr);
939 /// Ditto
940 final void setFields(JITField[] fields...)
942 this.setFields(null, fields);
946 /// Class wrapper for gcc_jit_function
947 class JITFunction : JITObject
950 this()
952 super();
956 this(gcc_jit_function *func)
958 if (!func)
959 throw new JITError("Unknown error, got bad function");
960 super(gcc_jit_function_as_object(func));
963 /// Returns the internal gcc_jit_function object.
964 final gcc_jit_function *getFunction()
966 // Manual downcast.
967 return cast(gcc_jit_function *)(this.getObject());
970 /// Dump function to dot file.
971 final void dump(string path)
973 gcc_jit_function_dump_to_dot(this.getFunction(), path.toStringz());
976 /// Get a specific param of a function by index.
977 final JITParam getParam(int index)
979 auto result = gcc_jit_function_get_param(this.getFunction(), index);
980 return new JITParam(result);
983 /// Create a new JITBlock.
984 /// The name can be null, or you can give it a meaningful name, which may
985 /// show up in dumps of the internal representation, and in error messages.
986 final JITBlock newBlock()
988 auto result = gcc_jit_function_new_block(this.getFunction(), null);
989 return new JITBlock(result);
992 /// Ditto
993 final JITBlock newBlock(string name)
995 auto result = gcc_jit_function_new_block(this.getFunction(),
996 name.toStringz());
997 return new JITBlock(result);
1000 /// Create a new local variable.
1001 final JITLValue newLocal(JITLocation loc, JITType type, string name)
1003 auto result = gcc_jit_function_new_local(this.getFunction(),
1004 loc ? loc.getLocation() : null,
1005 type.getType(),
1006 name.toStringz());
1007 return new JITLValue(result);
1010 /// Ditto
1011 final JITLValue newLocal(JITType type, string name)
1013 return this.newLocal(null, type, name);
1018 /// Class wrapper for gcc_jit_block
1019 class JITBlock : JITObject
1022 this()
1024 super();
1028 this(gcc_jit_block *block)
1030 super(gcc_jit_block_as_object(block));
1033 /// Returns the internal gcc_jit_block object.
1034 final gcc_jit_block *getBlock()
1036 // Manual downcast.
1037 return cast(gcc_jit_block *)(this.getObject());
1040 /// Returns the JITFunction this JITBlock is within.
1041 final JITFunction getFunction()
1043 auto result = gcc_jit_block_get_function(this.getBlock());
1044 return new JITFunction(result);
1047 /// Add evaluation of an rvalue, discarding the result.
1048 final void addEval(JITLocation loc, JITRValue rvalue)
1050 gcc_jit_block_add_eval(this.getBlock(),
1051 loc ? loc.getLocation() : null,
1052 rvalue.getRValue());
1055 /// Ditto
1056 final void addEval(JITRValue rvalue)
1058 return this.addEval(null, rvalue);
1061 /// Add evaluation of an rvalue, assigning the result to the given lvalue.
1062 /// This is equivalent to "lvalue = rvalue".
1063 final void addAssignment(JITLocation loc, JITLValue lvalue, JITRValue rvalue)
1065 gcc_jit_block_add_assignment(this.getBlock(),
1066 loc ? loc.getLocation() : null,
1067 lvalue.getLValue(), rvalue.getRValue());
1070 /// Ditto
1071 final void addAssignment(JITLValue lvalue, JITRValue rvalue)
1073 return this.addAssignment(null, lvalue, rvalue);
1076 /// Add evaluation of an rvalue, using the result to modify an lvalue.
1077 /// This is equivalent to "lvalue op= rvalue".
1078 final void addAssignmentOp(JITLocation loc, JITLValue lvalue,
1079 JITBinaryOp op, JITRValue rvalue)
1081 gcc_jit_block_add_assignment_op(this.getBlock(),
1082 loc ? loc.getLocation() : null,
1083 lvalue.getLValue(), op, rvalue.getRValue());
1086 /// Ditto
1087 final void addAssignmentOp(JITLValue lvalue, JITBinaryOp op, JITRValue rvalue)
1089 return this.addAssignmentOp(null, lvalue, op, rvalue);
1092 /// A way to add a function call to the body of a function being
1093 /// defined, with various number of args.
1094 final JITRValue addCall(JITLocation loc, JITFunction func, JITRValue[] args...)
1096 JITRValue rv = this.getContext().newCall(loc, func, args);
1097 this.addEval(loc, rv);
1098 return rv;
1101 /// Ditto
1102 final JITRValue addCall(JITFunction func, JITRValue[] args...)
1104 return this.addCall(null, func, args);
1107 /// Add a no-op textual comment to the internal representation of the code.
1108 /// It will be optimized away, but visible in the dumps seens via
1109 /// JITBoolOption.DUMP_INITIAL_TREE and JITBoolOption.DUMP_INITIAL_GIMPLE.
1110 final void addComment(JITLocation loc, string text)
1112 gcc_jit_block_add_comment(this.getBlock(),
1113 loc ? loc.getLocation() : null,
1114 text.toStringz());
1117 /// Ditto
1118 final void addComment(string text)
1120 return this.addComment(null, text);
1123 /// Terminate a block by adding evaluation of an rvalue, branching on the
1124 /// result to the appropriate successor block.
1125 final void endWithConditional(JITLocation loc, JITRValue val,
1126 JITBlock on_true, JITBlock on_false)
1128 gcc_jit_block_end_with_conditional(this.getBlock(),
1129 loc ? loc.getLocation() : null,
1130 val.getRValue(),
1131 on_true.getBlock(),
1132 on_false.getBlock());
1135 /// Ditto
1136 final void endWithConditional(JITRValue val, JITBlock on_true, JITBlock on_false)
1138 return this.endWithConditional(null, val, on_true, on_false);
1141 /// Terminate a block by adding a jump to the given target block.
1142 /// This is equivalent to "goto target".
1143 final void endWithJump(JITLocation loc, JITBlock target)
1145 gcc_jit_block_end_with_jump(this.getBlock(),
1146 loc ? loc.getLocation() : null,
1147 target.getBlock());
1150 /// Ditto
1151 final void endWithJump(JITBlock target)
1153 return this.endWithJump(null, target);
1156 /// Terminate a block by adding evaluation of an rvalue, returning the value.
1157 /// This is equivalent to "return rvalue".
1158 final void endWithReturn(JITLocation loc, JITRValue rvalue)
1160 gcc_jit_block_end_with_return(this.getBlock(),
1161 loc ? loc.getLocation() : null,
1162 rvalue.getRValue());
1165 /// Ditto
1166 final void endWithReturn(JITRValue rvalue)
1168 return this.endWithReturn(null, rvalue);
1171 /// Terminate a block by adding a valueless return, for use within a
1172 /// function with "void" return type.
1173 /// This is equivalent to "return".
1174 final void endWithReturn(JITLocation loc = null)
1176 gcc_jit_block_end_with_void_return(this.getBlock(),
1177 loc ? loc.getLocation() : null);
1181 /// Class wrapper for gcc_jit_rvalue
1182 class JITRValue : JITObject
1185 this()
1187 super();
1191 this(gcc_jit_rvalue *rvalue)
1193 if (!rvalue)
1194 throw new JITError("Unknown error, got bad rvalue");
1195 super(gcc_jit_rvalue_as_object(rvalue));
1198 /// Returns the internal gcc_jit_rvalue object.
1199 final gcc_jit_rvalue *getRValue()
1201 // Manual downcast.
1202 return cast(gcc_jit_rvalue *)(this.getObject());
1205 /// Returns the JITType of the rvalue.
1206 final JITType getType()
1208 auto result = gcc_jit_rvalue_get_type(this.getRValue());
1209 return new JITType(result);
1212 /// Accessing a field of an rvalue of struct type.
1213 /// This is equivalent to "(value).field".
1214 JITRValue accessField(JITLocation loc, JITField field)
1216 auto result = gcc_jit_rvalue_access_field(this.getRValue(),
1217 loc ? loc.getLocation() : null,
1218 field.getField());
1219 return new JITRValue(result);
1222 /// Ditto
1223 JITRValue accessField(JITField field)
1225 return this.accessField(null, field);
1228 /// Accessing a field of an rvalue of pointer type.
1229 /// This is equivalent to "(*value).field".
1230 final JITLValue dereferenceField(JITLocation loc, JITField field)
1232 auto result = gcc_jit_rvalue_dereference_field(this.getRValue(),
1233 loc ? loc.getLocation() : null,
1234 field.getField());
1235 return new JITLValue(result);
1238 /// Ditto
1239 final JITLValue dereferenceField(JITField field)
1241 return this.dereferenceField(null, field);
1244 /// Dereferencing an rvalue of pointer type.
1245 /// This is equivalent to "*(value)".
1246 final JITLValue dereference(JITLocation loc = null)
1248 auto result = gcc_jit_rvalue_dereference(this.getRValue(),
1249 loc ? loc.getLocation() : null);
1250 return new JITLValue(result);
1253 /// Convert an rvalue to the given JITType. See JITContext.newCast for
1254 /// limitations.
1255 final JITRValue castTo(JITLocation loc, JITType type)
1257 return this.getContext().newCast(loc, this, type);
1260 /// Ditto
1261 final JITRValue castTo(JITType type)
1263 return this.castTo(null, type);
1266 /// Ditto
1267 final JITRValue castTo(JITLocation loc, JITTypeKind kind)
1269 return this.castTo(loc, this.getContext().getType(kind));
1272 /// Ditto
1273 final JITRValue castTo(JITTypeKind kind)
1275 return this.castTo(null, this.getContext().getType(kind));
1279 /// Class wrapper for gcc_jit_lvalue
1280 class JITLValue : JITRValue
1283 this()
1285 super();
1289 this(gcc_jit_lvalue *lvalue)
1291 if (!lvalue)
1292 throw new JITError("Unknown error, got bad lvalue");
1293 super(gcc_jit_lvalue_as_rvalue(lvalue));
1296 /// Returns the internal gcc_jit_lvalue object.
1297 final gcc_jit_lvalue *getLValue()
1299 // Manual downcast.
1300 return cast(gcc_jit_lvalue *)(this.getObject());
1303 /// Accessing a field of an lvalue of struct type.
1304 /// This is equivalent to "(value).field = ...".
1305 override JITLValue accessField(JITLocation loc, JITField field)
1307 auto result = gcc_jit_lvalue_access_field(this.getLValue(),
1308 loc ? loc.getLocation() : null,
1309 field.getField());
1310 return new JITLValue(result);
1313 /// Ditto
1314 override JITLValue accessField(JITField field)
1316 return this.accessField(null, field);
1319 /// Taking the address of an lvalue.
1320 /// This is equivalent to "&(value)".
1321 final JITRValue getAddress(JITLocation loc = null)
1323 auto result = gcc_jit_lvalue_get_address(this.getLValue(),
1324 loc ? loc.getLocation() : null);
1325 return new JITRValue(result);
1329 /// Class wrapper for gcc_jit_param
1330 class JITParam : JITLValue
1333 this()
1335 super();
1339 this(gcc_jit_param *param)
1341 if (!param)
1342 throw new JITError("Unknown error, got bad param");
1343 super(gcc_jit_param_as_lvalue(param));
1346 /// Returns the internal gcc_jit_param object.
1347 final gcc_jit_param *getParam()
1349 // Manual downcast.
1350 return cast(gcc_jit_param *)(this.getObject());
1354 /// Class wrapper for gcc_jit_result
1355 final class JITResult
1358 this()
1360 this.m_inner_result = null;
1364 this(gcc_jit_result *result)
1366 if (!result)
1367 throw new JITError("Unknown error, got bad result");
1368 this.m_inner_result = result;
1371 /// Returns the internal gcc_jit_result object.
1372 gcc_jit_result *getResult()
1374 return this.m_inner_result;
1377 /// Locate a given function within the built machine code.
1378 /// This will need to be cast to a function pointer of the correct type
1379 /// before it can be called.
1380 void *getCode(string name)
1382 return gcc_jit_result_get_code(this.getResult(), name.toStringz());
1385 /// Locate a given global within the built machine code.
1386 /// It must have been created using JITGlobalKind.EXPORTED.
1387 /// This returns is a pointer to the global.
1388 void *getGlobal(string name)
1390 return gcc_jit_result_get_global(this.getResult(), name.toStringz());
1393 /// Once we're done with the code, this unloads the built .so file.
1394 /// After this call, it's no longer valid to use this JITResult.
1395 void release()
1397 gcc_jit_result_release(this.getResult());
1400 private:
1401 gcc_jit_result *m_inner_result;
1404 /// Kinds of function.
1405 enum JITFunctionKind : gcc_jit_function_kind
1407 /// Function is defined by the client code and visible by name
1408 /// outside of the JIT.
1409 EXPORTED = GCC_JIT_FUNCTION_EXPORTED,
1410 /// Function is defined by the client code, but is invisible
1411 /// outside of the JIT.
1412 INTERNAL = GCC_JIT_FUNCTION_INTERNAL,
1413 /// Function is not defined by the client code; we're merely
1414 /// referring to it.
1415 IMPORTED = GCC_JIT_FUNCTION_IMPORTED,
1416 /// Function is only ever inlined into other functions, and is
1417 /// invisible outside of the JIT.
1418 ALWAYS_INLINE = GCC_JIT_FUNCTION_ALWAYS_INLINE,
1421 /// Kinds of global.
1422 enum JITGlobalKind : gcc_jit_global_kind
1424 /// Global is defined by the client code and visible by name
1425 /// outside of this JIT context.
1426 EXPORTED = GCC_JIT_GLOBAL_EXPORTED,
1427 /// Global is defined by the client code, but is invisible
1428 /// outside of this JIT context. Analogous to a "static" global.
1429 INTERNAL = GCC_JIT_GLOBAL_INTERNAL,
1430 /// Global is not defined by the client code; we're merely
1431 /// referring to it. Analogous to using an "extern" global.
1432 IMPORTED = GCC_JIT_GLOBAL_IMPORTED,
1435 /// Standard types.
1436 enum JITTypeKind : gcc_jit_types
1438 /// C's void type.
1439 VOID = GCC_JIT_TYPE_VOID,
1441 /// C's void* type.
1442 VOID_PTR = GCC_JIT_TYPE_VOID_PTR,
1444 /// C++'s bool type.
1445 BOOL = GCC_JIT_TYPE_BOOL,
1447 /// C's char type.
1448 CHAR = GCC_JIT_TYPE_CHAR,
1450 /// C's signed char type.
1451 SIGNED_CHAR = GCC_JIT_TYPE_SIGNED_CHAR,
1453 /// C's unsigned char type.
1454 UNSIGNED_CHAR = GCC_JIT_TYPE_UNSIGNED_CHAR,
1456 /// C's short type.
1457 SHORT = GCC_JIT_TYPE_SHORT,
1459 /// C's unsigned short type.
1460 UNSIGNED_SHORT = GCC_JIT_TYPE_UNSIGNED_SHORT,
1462 /// C's int type.
1463 INT = GCC_JIT_TYPE_INT,
1465 /// C's unsigned int type.
1466 UNSIGNED_INT = GCC_JIT_TYPE_UNSIGNED_INT,
1468 /// C's long type.
1469 LONG = GCC_JIT_TYPE_LONG,
1471 /// C's unsigned long type.
1472 UNSIGNED_LONG = GCC_JIT_TYPE_UNSIGNED_LONG,
1474 /// C99's long long type.
1475 LONG_LONG = GCC_JIT_TYPE_LONG_LONG,
1477 /// C99's unsigned long long type.
1478 UNSIGNED_LONG_LONG = GCC_JIT_TYPE_UNSIGNED_LONG_LONG,
1480 /// Single precision floating point type.
1481 FLOAT = GCC_JIT_TYPE_FLOAT,
1483 /// Double precision floating point type.
1484 DOUBLE = GCC_JIT_TYPE_DOUBLE,
1486 /// Largest supported floating point type.
1487 LONG_DOUBLE = GCC_JIT_TYPE_LONG_DOUBLE,
1489 /// C's const char* type.
1490 CONST_CHAR_PTR = GCC_JIT_TYPE_CONST_CHAR_PTR,
1492 /// C's usize type.
1493 SIZE_T = GCC_JIT_TYPE_SIZE_T,
1495 /// C's FILE* type.
1496 FILE_PTR = GCC_JIT_TYPE_FILE_PTR,
1498 /// Single precision complex float type.
1499 COMPLEX_FLOAT = GCC_JIT_TYPE_COMPLEX_FLOAT,
1501 /// Double precision complex float type.
1502 COMPLEX_DOUBLE = GCC_JIT_TYPE_COMPLEX_DOUBLE,
1504 /// Largest supported complex float type.
1505 COMPLEX_LONG_DOUBLE = GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE,
1508 /// Kinds of unary ops.
1509 enum JITUnaryOp : gcc_jit_unary_op
1511 /// Negate an arithmetic value.
1512 /// This is equivalent to "-(value)".
1513 MINUS = GCC_JIT_UNARY_OP_MINUS,
1514 /// Bitwise negation of an integer value (one's complement).
1515 /// This is equivalent to "~(value)".
1516 BITWISE_NEGATE = GCC_JIT_UNARY_OP_BITWISE_NEGATE,
1517 /// Logical negation of an arithmetic or pointer value.
1518 /// This is equivalent to "!(value)".
1519 LOGICAL_NEGATE = GCC_JIT_UNARY_OP_LOGICAL_NEGATE,
1522 /// Kinds of binary ops.
1523 enum JITBinaryOp : gcc_jit_binary_op
1525 /// Addition of arithmetic values.
1526 /// This is equivalent to "(a) + (b)".
1527 PLUS = GCC_JIT_BINARY_OP_PLUS,
1528 /// Subtraction of arithmetic values.
1529 /// This is equivalent to "(a) - (b)".
1530 MINUS = GCC_JIT_BINARY_OP_MINUS,
1531 /// Multiplication of a pair of arithmetic values.
1532 /// This is equivalent to "(a) * (b)".
1533 MULT = GCC_JIT_BINARY_OP_MULT,
1534 /// Quotient of division of arithmetic values.
1535 /// This is equivalent to "(a) / (b)".
1536 DIVIDE = GCC_JIT_BINARY_OP_DIVIDE,
1537 /// Remainder of division of arithmetic values.
1538 /// This is equivalent to "(a) % (b)".
1539 MODULO = GCC_JIT_BINARY_OP_MODULO,
1540 /// Bitwise AND.
1541 /// This is equivalent to "(a) & (b)".
1542 BITWISE_AND = GCC_JIT_BINARY_OP_BITWISE_AND,
1543 /// Bitwise exclusive OR.
1544 /// This is equivalent to "(a) ^ (b)".
1545 BITWISE_XOR = GCC_JIT_BINARY_OP_BITWISE_XOR,
1546 /// Bitwise inclusive OR.
1547 /// This is equivalent to "(a) | (b)".
1548 BITWISE_OR = GCC_JIT_BINARY_OP_BITWISE_OR,
1549 /// Logical AND.
1550 /// This is equivalent to "(a) && (b)".
1551 LOGICAL_AND = GCC_JIT_BINARY_OP_LOGICAL_AND,
1552 /// Logical OR.
1553 /// This is equivalent to "(a) || (b)".
1554 LOGICAL_OR = GCC_JIT_BINARY_OP_LOGICAL_OR,
1555 /// Left shift.
1556 /// This is equivalent to "(a) << (b)".
1557 LSHIFT = GCC_JIT_BINARY_OP_LSHIFT,
1558 /// Right shift.
1559 /// This is equivalent to "(a) >> (b)".
1560 RSHIFT = GCC_JIT_BINARY_OP_RSHIFT,
1563 /// Kinds of comparison.
1564 enum JITComparison : gcc_jit_comparison
1566 /// This is equivalent to "(a) == (b)".
1567 EQ = GCC_JIT_COMPARISON_EQ,
1568 /// This is equivalent to "(a) != (b)".
1569 NE = GCC_JIT_COMPARISON_NE,
1570 /// This is equivalent to "(a) < (b)".
1571 LT = GCC_JIT_COMPARISON_LT,
1572 /// This is equivalent to "(a) <= (b)".
1573 LE = GCC_JIT_COMPARISON_LE,
1574 /// This is equivalent to "(a) > (b)".
1575 GT = GCC_JIT_COMPARISON_GT,
1576 /// This is equivalent to "(a) >= (b)".
1577 GE = GCC_JIT_COMPARISON_GE,
1580 /// String options
1581 enum JITStrOption : gcc_jit_str_option
1583 /// The name of the program, for use as a prefix when printing error
1584 /// messages to stderr. If None, or default, "libgccjit.so" is used.
1585 PROGNAME = GCC_JIT_STR_OPTION_PROGNAME,
1588 /// Integer options
1589 enum JITIntOption : gcc_jit_int_option
1591 /// How much to optimize the code.
1593 /// Valid values are 0-3, corresponding to GCC's command-line options
1594 /// -O0 through -O3.
1596 /// The default value is 0 (unoptimized).
1597 OPTIMIZATION_LEVEL = GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL,
1600 /// Boolean options
1601 enum JITBoolOption : gcc_jit_bool_option
1603 /// If true, JITContext.compile() will attempt to do the right thing
1604 /// so that if you attach a debugger to the process, it will be able
1605 /// to inspect variables and step through your code.
1607 /// Note that you can’t step through code unless you set up source
1608 /// location information for the code (by creating and passing in
1609 /// JITLocation instances).
1610 DEBUGINFO = GCC_JIT_BOOL_OPTION_DEBUGINFO,
1612 /// If true, JITContext.compile() will dump its initial "tree"
1613 /// representation of your code to stderr, before any optimizations.
1614 DUMP_INITIAL_TREE = GCC_JIT_BOOL_OPTION_DUMP_INITIAL_TREE,
1616 /// If true, JITContext.compile() will dump its initial "gimple"
1617 /// representation of your code to stderr, before any optimizations
1618 /// are performed. The dump resembles C code.
1619 DUMP_INITIAL_GIMPLE = GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE,
1621 /// If true, JITContext.compile() will dump the final generated code
1622 /// to stderr, in the form of assembly language.
1623 DUMP_GENERATED_CODE = GCC_JIT_BOOL_OPTION_DUMP_GENERATED_CODE,
1625 /// If true, JITContext.compile() will print information to stderr
1626 /// on the actions it is performing, followed by a profile showing
1627 /// the time taken and memory usage of each phase.
1628 DUMP_SUMMARY = GCC_JIT_BOOL_OPTION_DUMP_SUMMARY,
1630 /// If true, JITContext.compile() will dump copious amounts of
1631 /// information on what it’s doing to various files within a
1632 /// temporary directory. Use JITBoolOption.KEEP_INTERMEDIATES
1633 /// to see the results. The files are intended to be human-readable,
1634 /// but the exact files and their formats are subject to change.
1635 DUMP_EVERYTHING = GCC_JIT_BOOL_OPTION_DUMP_EVERYTHING,
1637 /// If true, libgccjit will aggressively run its garbage collector,
1638 /// to shake out bugs (greatly slowing down the compile). This is
1639 /// likely to only be of interest to developers of the library.
1640 SELFCHECK_GC = GCC_JIT_BOOL_OPTION_SELFCHECK_GC,
1642 /// If true, the JITContext will not clean up intermediate files
1643 /// written to the filesystem, and will display their location on
1644 /// stderr.
1645 KEEP_INTERMEDIATES = GCC_JIT_BOOL_OPTION_KEEP_INTERMEDIATES,
1650 /* A pure C API to enable client code to embed GCC as a JIT-compiler.
1652 This file has been modified from the libgccjit.h header to work with
1653 the D compiler. The original file is part of the GCC distribution
1654 and is licensed under the following terms.
1656 Copyright (C) 2013-2015 Free Software Foundation, Inc.
1658 This program is free software: you can redistribute it and/or modify
1659 it under the terms of the GNU General Public License as published by
1660 the Free Software Foundation, either version 3 of the License, or
1661 (at your option) any later version.
1663 This program is distributed in the hope that it will be useful,
1664 but WITHOUT ANY WARRANTY; without even the implied warranty of
1665 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1666 GNU General Public License for more details.
1668 You should have received a copy of the GNU General Public License
1669 along with this program. If not, see <http://www.gnu.org/licenses/>.
1672 import core.stdc.stdio;
1674 extern(C):
1676 /**********************************************************************
1677 Data structures.
1678 **********************************************************************/
1679 /* All structs within the API are opaque. */
1681 /* A gcc_jit_context encapsulates the state of a compilation.
1682 You can set up options on it, and add types, functions and code, using
1683 the API below.
1685 Invoking gcc_jit_context_compile on it gives you a gcc_jit_result *
1686 (or NULL), representing in-memory machine code.
1688 You can call gcc_jit_context_compile repeatedly on one context, giving
1689 multiple independent results.
1691 Similarly, you can call gcc_jit_context_compile_to_file on a context
1692 to compile to disk.
1694 Eventually you can call gcc_jit_context_release to clean up the
1695 context; any in-memory results created from it are still usable, and
1696 should be cleaned up via gcc_jit_result_release. */
1697 struct gcc_jit_context;
1699 /* A gcc_jit_result encapsulates the result of an in-memory compilation. */
1700 struct gcc_jit_result;
1702 /* An object created within a context. Such objects are automatically
1703 cleaned up when the context is released.
1705 The class hierarchy looks like this:
1707 +- gcc_jit_object
1708 +- gcc_jit_location
1709 +- gcc_jit_type
1710 +- gcc_jit_struct
1711 +- gcc_jit_field
1712 +- gcc_jit_function
1713 +- gcc_jit_block
1714 +- gcc_jit_rvalue
1715 +- gcc_jit_lvalue
1716 +- gcc_jit_param
1718 struct gcc_jit_object;
1720 /* A gcc_jit_location encapsulates a source code location, so that
1721 you can (optionally) associate locations in your language with
1722 statements in the JIT-compiled code, allowing the debugger to
1723 single-step through your language.
1725 Note that to do so, you also need to enable
1726 GCC_JIT_BOOL_OPTION_DEBUGINFO
1727 on the gcc_jit_context.
1729 gcc_jit_location instances are optional; you can always pass
1730 NULL. */
1731 struct gcc_jit_location;
1733 /* A gcc_jit_type encapsulates a type e.g. "int" or a "struct foo*". */
1734 struct gcc_jit_type;
1736 /* A gcc_jit_field encapsulates a field within a struct; it is used
1737 when creating a struct type (using gcc_jit_context_new_struct_type).
1738 Fields cannot be shared between structs. */
1739 struct gcc_jit_field;
1741 /* A gcc_jit_struct encapsulates a struct type, either one that we have
1742 the layout for, or an opaque type. */
1743 struct gcc_jit_struct;
1745 /* A gcc_jit_function encapsulates a function: either one that you're
1746 creating yourself, or a reference to one that you're dynamically
1747 linking to within the rest of the process. */
1748 struct gcc_jit_function;
1750 /* A gcc_jit_block encapsulates a "basic block" of statements within a
1751 function (i.e. with one entry point and one exit point).
1753 Every block within a function must be terminated with a conditional,
1754 a branch, or a return.
1756 The blocks within a function form a directed graph.
1758 The entrypoint to the function is the first block created within
1761 All of the blocks in a function must be reachable via some path from
1762 the first block.
1764 It's OK to have more than one "return" from a function (i.e. multiple
1765 blocks that terminate by returning). */
1766 struct gcc_jit_block;
1768 /* A gcc_jit_rvalue is an expression within your code, with some type. */
1769 struct gcc_jit_rvalue;
1771 /* A gcc_jit_lvalue is a storage location within your code (e.g. a
1772 variable, a parameter, etc). It is also a gcc_jit_rvalue; use
1773 gcc_jit_lvalue_as_rvalue to cast. */
1774 struct gcc_jit_lvalue;
1776 /* A gcc_jit_param is a function parameter, used when creating a
1777 gcc_jit_function. It is also a gcc_jit_lvalue (and thus also an
1778 rvalue); use gcc_jit_param_as_lvalue to convert. */
1779 struct gcc_jit_param;
1781 /* Acquire a JIT-compilation context. */
1782 gcc_jit_context *gcc_jit_context_acquire();
1784 /* Release the context. After this call, it's no longer valid to use
1785 the ctxt. */
1786 void gcc_jit_context_release(gcc_jit_context *ctxt);
1788 /* Options taking string values. */
1789 alias gcc_jit_str_option = uint;
1790 enum : gcc_jit_str_option
1792 /* The name of the program, for use as a prefix when printing error
1793 messages to stderr. If NULL, or default, "libgccjit.so" is used. */
1794 GCC_JIT_STR_OPTION_PROGNAME,
1796 GCC_JIT_NUM_STR_OPTIONS
1799 /* Options taking int values. */
1800 alias gcc_jit_int_option = uint;
1801 enum : gcc_jit_int_option
1803 /* How much to optimize the code.
1804 Valid values are 0-3, corresponding to GCC's command-line options
1805 -O0 through -O3.
1807 The default value is 0 (unoptimized). */
1808 GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL,
1810 GCC_JIT_NUM_INT_OPTIONS
1813 /* Options taking boolean values.
1814 These all default to "false". */
1815 alias gcc_jit_bool_option = uint;
1816 enum : gcc_jit_bool_option
1818 /* If true, gcc_jit_context_compile will attempt to do the right
1819 thing so that if you attach a debugger to the process, it will
1820 be able to inspect variables and step through your code.
1822 Note that you can't step through code unless you set up source
1823 location information for the code (by creating and passing in
1824 gcc_jit_location instances). */
1825 GCC_JIT_BOOL_OPTION_DEBUGINFO,
1827 /* If true, gcc_jit_context_compile will dump its initial "tree"
1828 representation of your code to stderr (before any
1829 optimizations). */
1830 GCC_JIT_BOOL_OPTION_DUMP_INITIAL_TREE,
1832 /* If true, gcc_jit_context_compile will dump the "gimple"
1833 representation of your code to stderr, before any optimizations
1834 are performed. The dump resembles C code. */
1835 GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE,
1837 /* If true, gcc_jit_context_compile will dump the final
1838 generated code to stderr, in the form of assembly language. */
1839 GCC_JIT_BOOL_OPTION_DUMP_GENERATED_CODE,
1841 /* If true, gcc_jit_context_compile will print information to stderr
1842 on the actions it is performing, followed by a profile showing
1843 the time taken and memory usage of each phase.
1845 GCC_JIT_BOOL_OPTION_DUMP_SUMMARY,
1847 /* If true, gcc_jit_context_compile will dump copious
1848 amount of information on what it's doing to various
1849 files within a temporary directory. Use
1850 GCC_JIT_BOOL_OPTION_KEEP_INTERMEDIATES (see below) to
1851 see the results. The files are intended to be human-readable,
1852 but the exact files and their formats are subject to change.
1854 GCC_JIT_BOOL_OPTION_DUMP_EVERYTHING,
1856 /* If true, libgccjit will aggressively run its garbage collector, to
1857 shake out bugs (greatly slowing down the compile). This is likely
1858 to only be of interest to developers *of* the library. It is
1859 used when running the selftest suite. */
1860 GCC_JIT_BOOL_OPTION_SELFCHECK_GC,
1862 /* If true, gcc_jit_context_release will not clean up
1863 intermediate files written to the filesystem, and will display
1864 their location on stderr. */
1865 GCC_JIT_BOOL_OPTION_KEEP_INTERMEDIATES,
1867 GCC_JIT_NUM_BOOL_OPTIONS
1870 /* Set a string option on the given context.
1872 The context directly stores the (const char *), so the passed string
1873 must outlive the context. */
1874 void gcc_jit_context_set_str_option(gcc_jit_context *ctxt,
1875 gcc_jit_str_option opt,
1876 in char *value);
1878 /* Set an int option on the given context. */
1879 void gcc_jit_context_set_int_option(gcc_jit_context *ctxt,
1880 gcc_jit_int_option opt,
1881 int value);
1883 /* Set a boolean option on the given context.
1885 Zero is "false" (the default), non-zero is "true". */
1886 void gcc_jit_context_set_bool_option(gcc_jit_context *ctxt,
1887 gcc_jit_bool_option opt,
1888 int value);
1890 /* Compile the context to in-memory machine code.
1892 This can be called more that once on a given context,
1893 although any errors that occur will block further compilation. */
1895 gcc_jit_result *gcc_jit_context_compile(gcc_jit_context *ctxt);
1897 /* Kinds of ahead-of-time compilation, for use with
1898 gcc_jit_context_compile_to_file. */
1900 alias gcc_jit_output_kind = uint;
1901 enum : gcc_jit_output_kind
1903 /* Compile the context to an assembler file. */
1904 GCC_JIT_OUTPUT_KIND_ASSEMBLER,
1906 /* Compile the context to an object file. */
1907 GCC_JIT_OUTPUT_KIND_OBJECT_FILE,
1909 /* Compile the context to a dynamic library. */
1910 GCC_JIT_OUTPUT_KIND_DYNAMIC_LIBRARY,
1912 /* Compile the context to an executable. */
1913 GCC_JIT_OUTPUT_KIND_EXECUTABLE
1916 /* Compile the context to a file of the given kind.
1918 This can be called more that once on a given context,
1919 although any errors that occur will block further compilation. */
1921 void gcc_jit_context_compile_to_file(gcc_jit_context *ctxt,
1922 gcc_jit_output_kind output_kind,
1923 in char *output_path);
1925 /* To help with debugging: dump a C-like representation to the given path,
1926 describing what's been set up on the context.
1928 If "update_locations" is true, then also set up gcc_jit_location
1929 information throughout the context, pointing at the dump file as if it
1930 were a source file. This may be of use in conjunction with
1931 GCC_JIT_BOOL_OPTION_DEBUGINFO to allow stepping through the code in a
1932 debugger. */
1933 void gcc_jit_context_dump_to_file(gcc_jit_context *ctxt,
1934 in char *path,
1935 int update_locations);
1937 /* To help with debugging; enable ongoing logging of the context's
1938 activity to the given FILE *.
1940 The caller remains responsible for closing "logfile".
1942 Params "flags" and "verbosity" are reserved for future use, and
1943 must both be 0 for now. */
1944 void gcc_jit_context_set_logfile(gcc_jit_context *ctxt,
1945 FILE *logfile,
1946 int flags,
1947 int verbosity);
1949 /* To be called after any API call, this gives the first error message
1950 that occurred on the context.
1952 The returned string is valid for the rest of the lifetime of the
1953 context.
1955 If no errors occurred, this will be NULL. */
1956 const(char) *gcc_jit_context_get_first_error(gcc_jit_context *ctxt);
1958 /* To be called after any API call, this gives the last error message
1959 that occurred on the context.
1961 If no errors occurred, this will be NULL.
1963 If non-NULL, the returned string is only guaranteed to be valid until
1964 the next call to libgccjit relating to this context. */
1965 const(char) *gcc_jit_context_get_last_error(gcc_jit_context *ctxt);
1967 /* Locate a given function within the built machine code.
1968 This will need to be cast to a function pointer of the
1969 correct type before it can be called. */
1970 void *gcc_jit_result_get_code(gcc_jit_result *result,
1971 in char *funcname);
1973 /* Locate a given global within the built machine code.
1974 It must have been created using GCC_JIT_GLOBAL_EXPORTED.
1975 This is a ptr to the global, so e.g. for an int this is an int *. */
1976 void *gcc_jit_result_get_global (gcc_jit_result *result,
1977 in char *name);
1979 /* Once we're done with the code, this unloads the built .so file.
1980 This cleans up the result; after calling this, it's no longer
1981 valid to use the result. */
1982 void gcc_jit_result_release(gcc_jit_result *result);
1985 /**********************************************************************
1986 Functions for creating "contextual" objects.
1988 All objects created by these functions share the lifetime of the context
1989 they are created within, and are automatically cleaned up for you when
1990 you call gcc_jit_context_release on the context.
1992 Note that this means you can't use references to them after you've
1993 released their context.
1995 All (const char *) string arguments passed to these functions are
1996 copied, so you don't need to keep them around. Note that this *isn't*
1997 the case for other parts of the API.
1999 You create code by adding a sequence of statements to blocks.
2000 **********************************************************************/
2002 /**********************************************************************
2003 The base class of "contextual" object.
2004 **********************************************************************/
2005 /* Which context is "obj" within? */
2006 gcc_jit_context *gcc_jit_object_get_context(gcc_jit_object *obj);
2008 /* Get a human-readable description of this object.
2009 The string buffer is created the first time this is called on a given
2010 object, and persists until the object's context is released. */
2011 const(char) *gcc_jit_object_get_debug_string(gcc_jit_object *obj);
2013 /**********************************************************************
2014 Debugging information.
2015 **********************************************************************/
2017 /* Creating source code locations for use by the debugger.
2018 Line and column numbers are 1-based. */
2019 gcc_jit_location *gcc_jit_context_new_location(gcc_jit_context *ctxt,
2020 in char *filename,
2021 int line,
2022 int column);
2024 /* Upcasting from location to object. */
2025 gcc_jit_object *gcc_jit_location_as_object(gcc_jit_location *loc);
2028 /**********************************************************************
2029 Types.
2030 **********************************************************************/
2032 /* Upcasting from type to object. */
2033 gcc_jit_object *gcc_jit_type_as_object(gcc_jit_type *type);
2035 /* Access to specific types. */
2036 alias gcc_jit_types = uint;
2037 enum : gcc_jit_types
2039 /* C's "void" type. */
2040 GCC_JIT_TYPE_VOID,
2042 /* "void *". */
2043 GCC_JIT_TYPE_VOID_PTR,
2045 /* C++'s bool type; also C99's "_Bool" type, aka "bool" if using
2046 stdbool.h. */
2047 GCC_JIT_TYPE_BOOL,
2049 /* Various integer types. */
2051 /* C's "char" (of some signedness) and the variants where the
2052 signedness is specified. */
2053 GCC_JIT_TYPE_CHAR,
2054 GCC_JIT_TYPE_SIGNED_CHAR,
2055 GCC_JIT_TYPE_UNSIGNED_CHAR,
2057 /* C's "short" and "unsigned short". */
2058 GCC_JIT_TYPE_SHORT, /* signed */
2059 GCC_JIT_TYPE_UNSIGNED_SHORT,
2061 /* C's "int" and "unsigned int". */
2062 GCC_JIT_TYPE_INT, /* signed */
2063 GCC_JIT_TYPE_UNSIGNED_INT,
2065 /* C's "long" and "unsigned long". */
2066 GCC_JIT_TYPE_LONG, /* signed */
2067 GCC_JIT_TYPE_UNSIGNED_LONG,
2069 /* C99's "long long" and "unsigned long long". */
2070 GCC_JIT_TYPE_LONG_LONG, /* signed */
2071 GCC_JIT_TYPE_UNSIGNED_LONG_LONG,
2073 /* Floating-point types */
2075 GCC_JIT_TYPE_FLOAT,
2076 GCC_JIT_TYPE_DOUBLE,
2077 GCC_JIT_TYPE_LONG_DOUBLE,
2079 /* C type: (const char *). */
2080 GCC_JIT_TYPE_CONST_CHAR_PTR,
2082 /* The C "usize" type. */
2083 GCC_JIT_TYPE_SIZE_T,
2085 /* C type: (FILE *) */
2086 GCC_JIT_TYPE_FILE_PTR,
2088 /* Complex numbers. */
2089 GCC_JIT_TYPE_COMPLEX_FLOAT,
2090 GCC_JIT_TYPE_COMPLEX_DOUBLE,
2091 GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE
2094 gcc_jit_type *gcc_jit_context_get_type(gcc_jit_context *ctxt,
2095 gcc_jit_types type_);
2097 gcc_jit_type *gcc_jit_context_get_int_type(gcc_jit_context *ctxt,
2098 int num_bytes, int is_signed);
2100 /* Constructing new types. */
2102 /* Given type "T", get type "T*". */
2103 gcc_jit_type *gcc_jit_type_get_pointer(gcc_jit_type *type);
2105 /* Given type "T", get type "const T". */
2106 gcc_jit_type *gcc_jit_type_get_const(gcc_jit_type *type);
2108 /* Given type "T", get type "volatile T". */
2109 gcc_jit_type *gcc_jit_type_get_volatile(gcc_jit_type *type);
2111 /* Given type "T", get type "T[N]" (for a constant N). */
2112 gcc_jit_type *gcc_jit_context_new_array_type(gcc_jit_context *ctxt,
2113 gcc_jit_location *loc,
2114 gcc_jit_type *element_type,
2115 int num_elements);
2117 /* Struct-handling. */
2118 gcc_jit_field *gcc_jit_context_new_field(gcc_jit_context *ctxt,
2119 gcc_jit_location *loc,
2120 gcc_jit_type *type,
2121 in char *name);
2123 /* Upcasting from field to object. */
2124 gcc_jit_object *gcc_jit_field_as_object(gcc_jit_field *field);
2126 /* Create a struct type from an array of fields. */
2127 gcc_jit_struct *gcc_jit_context_new_struct_type(gcc_jit_context *ctxt,
2128 gcc_jit_location *loc,
2129 in char *name,
2130 int num_fields,
2131 gcc_jit_field **fields);
2134 /* Create an opaque struct type. */
2135 gcc_jit_struct *gcc_jit_context_new_opaque_struct(gcc_jit_context *ctxt,
2136 gcc_jit_location *loc,
2137 in char *name);
2139 /* Upcast a struct to a type. */
2140 gcc_jit_type *gcc_jit_struct_as_type(gcc_jit_struct *struct_type);
2142 /* Populating the fields of a formerly-opaque struct type.
2143 This can only be called once on a given struct type. */
2144 void gcc_jit_struct_set_fields(gcc_jit_struct *struct_type,
2145 gcc_jit_location *loc,
2146 int num_fields,
2147 gcc_jit_field **fields);
2149 /* Unions work similarly to structs. */
2150 gcc_jit_type *gcc_jit_context_new_union_type(gcc_jit_context *ctxt,
2151 gcc_jit_location *loc,
2152 in char *name,
2153 int num_fields,
2154 gcc_jit_field **fields);
2156 /* Function pointers. */
2157 gcc_jit_type *gcc_jit_context_new_function_ptr_type(gcc_jit_context *ctxt,
2158 gcc_jit_location *loc,
2159 gcc_jit_type *return_type,
2160 int num_params,
2161 gcc_jit_type **param_types,
2162 int is_variadic);
2165 /**********************************************************************
2166 Constructing functions.
2167 **********************************************************************/
2168 /* Create a function param. */
2169 gcc_jit_param *gcc_jit_context_new_param(gcc_jit_context *ctxt,
2170 gcc_jit_location *loc,
2171 gcc_jit_type *type,
2172 in char *name);
2174 /* Upcasting from param to object. */
2175 gcc_jit_object *gcc_jit_param_as_object(gcc_jit_param *param);
2177 /* Upcasting from param to lvalue. */
2178 gcc_jit_lvalue *gcc_jit_param_as_lvalue(gcc_jit_param *param);
2180 /* Upcasting from param to rvalue. */
2181 gcc_jit_rvalue *gcc_jit_param_as_rvalue(gcc_jit_param *param);
2183 /* Kinds of function. */
2184 alias gcc_jit_function_kind = uint;
2185 enum : gcc_jit_function_kind
2187 /* Function is defined by the client code and visible
2188 by name outside of the JIT. */
2189 GCC_JIT_FUNCTION_EXPORTED,
2191 /* Function is defined by the client code, but is invisible
2192 outside of the JIT. Analogous to a "static" function. */
2193 GCC_JIT_FUNCTION_INTERNAL,
2195 /* Function is not defined by the client code; we're merely
2196 referring to it. Analogous to using an "extern" function from a
2197 header file. */
2198 GCC_JIT_FUNCTION_IMPORTED,
2200 /* Function is only ever inlined into other functions, and is
2201 invisible outside of the JIT.
2203 Analogous to prefixing with "inline" and adding
2204 __attribute__((always_inline)).
2206 Inlining will only occur when the optimization level is
2207 above 0; when optimization is off, this is essentially the
2208 same as GCC_JIT_FUNCTION_INTERNAL. */
2209 GCC_JIT_FUNCTION_ALWAYS_INLINE
2212 /* Create a function. */
2213 gcc_jit_function *gcc_jit_context_new_function(gcc_jit_context *ctxt,
2214 gcc_jit_location *loc,
2215 gcc_jit_function_kind kind,
2216 gcc_jit_type *return_type,
2217 in char *name,
2218 int num_params,
2219 gcc_jit_param **params,
2220 int is_variadic);
2222 /* Create a reference to a builtin function (sometimes called intrinsic functions). */
2223 gcc_jit_function *gcc_jit_context_get_builtin_function(gcc_jit_context *ctxt,
2224 in char *name);
2226 /* Upcasting from function to object. */
2227 gcc_jit_object *gcc_jit_function_as_object(gcc_jit_function *func);
2229 /* Get a specific param of a function by index. */
2230 gcc_jit_param *gcc_jit_function_get_param(gcc_jit_function *func, int index);
2232 /* Emit the function in graphviz format. */
2233 void gcc_jit_function_dump_to_dot(gcc_jit_function *func,
2234 in char *path);
2236 /* Create a block.
2238 The name can be NULL, or you can give it a meaningful name, which
2239 may show up in dumps of the internal representation, and in error
2240 messages. */
2241 gcc_jit_block *gcc_jit_function_new_block(gcc_jit_function *func,
2242 in char *name);
2244 /* Upcasting from block to object. */
2245 gcc_jit_object *gcc_jit_block_as_object(gcc_jit_block *block);
2247 /* Which function is this block within? */
2248 gcc_jit_function *gcc_jit_block_get_function(gcc_jit_block *block);
2250 /**********************************************************************
2251 lvalues, rvalues and expressions.
2252 **********************************************************************/
2253 alias gcc_jit_global_kind = uint;
2254 enum : gcc_jit_global_kind
2256 /* Global is defined by the client code and visible
2257 by name outside of this JIT context via gcc_jit_result_get_global. */
2258 GCC_JIT_GLOBAL_EXPORTED,
2260 /* Global is defined by the client code, but is invisible
2261 outside of this JIT context. Analogous to a "static" global. */
2262 GCC_JIT_GLOBAL_INTERNAL,
2264 /* Global is not defined by the client code; we're merely
2265 referring to it. Analogous to using an "extern" global from a
2266 header file. */
2267 GCC_JIT_GLOBAL_IMPORTED
2270 gcc_jit_lvalue *gcc_jit_context_new_global(gcc_jit_context *ctxt,
2271 gcc_jit_location *loc,
2272 gcc_jit_global_kind kind,
2273 gcc_jit_type *type,
2274 in char *name);
2276 /* Upcasting. */
2277 gcc_jit_object *gcc_jit_lvalue_as_object(gcc_jit_lvalue *lvalue);
2279 gcc_jit_rvalue *gcc_jit_lvalue_as_rvalue(gcc_jit_lvalue *lvalue);
2281 gcc_jit_object *gcc_jit_rvalue_as_object(gcc_jit_rvalue *rvalue);
2283 gcc_jit_type *gcc_jit_rvalue_get_type(gcc_jit_rvalue *rvalue);
2285 /* Integer constants. */
2286 gcc_jit_rvalue *gcc_jit_context_new_rvalue_from_int(gcc_jit_context *ctxt,
2287 gcc_jit_type *numeric_type,
2288 int value);
2290 gcc_jit_rvalue *gcc_jit_context_new_rvalue_from_long(gcc_jit_context *ctxt,
2291 gcc_jit_type *numeric_type,
2292 long value);
2294 gcc_jit_rvalue *gcc_jit_context_zero(gcc_jit_context *ctxt,
2295 gcc_jit_type *numeric_type);
2297 gcc_jit_rvalue *gcc_jit_context_one(gcc_jit_context *ctxt,
2298 gcc_jit_type *numeric_type);
2300 /* Floating-point constants. */
2301 gcc_jit_rvalue *gcc_jit_context_new_rvalue_from_double(gcc_jit_context *ctxt,
2302 gcc_jit_type *numeric_type,
2303 double value);
2305 /* Pointers. */
2306 gcc_jit_rvalue *gcc_jit_context_new_rvalue_from_ptr(gcc_jit_context *ctxt,
2307 gcc_jit_type *pointer_type,
2308 void *value);
2310 gcc_jit_rvalue *gcc_jit_context_null(gcc_jit_context *ctxt,
2311 gcc_jit_type *pointer_type);
2313 /* String literals. */
2314 gcc_jit_rvalue *gcc_jit_context_new_string_literal(gcc_jit_context *ctxt,
2315 in char *value);
2317 alias gcc_jit_unary_op = uint;
2318 enum : gcc_jit_unary_op
2320 /* Negate an arithmetic value; analogous to:
2321 -(EXPR)
2322 in C. */
2323 GCC_JIT_UNARY_OP_MINUS,
2325 /* Bitwise negation of an integer value (one's complement); analogous
2327 ~(EXPR)
2328 in C. */
2329 GCC_JIT_UNARY_OP_BITWISE_NEGATE,
2331 /* Logical negation of an arithmetic or pointer value; analogous to:
2332 !(EXPR)
2333 in C. */
2334 GCC_JIT_UNARY_OP_LOGICAL_NEGATE
2337 gcc_jit_rvalue *gcc_jit_context_new_unary_op(gcc_jit_context *ctxt,
2338 gcc_jit_location *loc,
2339 gcc_jit_unary_op op,
2340 gcc_jit_type *result_type,
2341 gcc_jit_rvalue *rvalue);
2343 alias gcc_jit_binary_op = uint;
2344 enum : gcc_jit_binary_op
2346 /* Addition of arithmetic values; analogous to:
2347 (EXPR_A) + (EXPR_B)
2348 in C.
2349 For pointer addition, use gcc_jit_context_new_array_access. */
2350 GCC_JIT_BINARY_OP_PLUS,
2352 /* Subtraction of arithmetic values; analogous to:
2353 (EXPR_A) - (EXPR_B)
2354 in C. */
2355 GCC_JIT_BINARY_OP_MINUS,
2357 /* Multiplication of a pair of arithmetic values; analogous to:
2358 (EXPR_A) * (EXPR_B)
2359 in C. */
2360 GCC_JIT_BINARY_OP_MULT,
2362 /* Quotient of division of arithmetic values; analogous to:
2363 (EXPR_A) / (EXPR_B)
2364 in C.
2365 The result type affects the kind of division: if the result type is
2366 integer-based, then the result is truncated towards zero, whereas
2367 a floating-point result type indicates floating-point division. */
2368 GCC_JIT_BINARY_OP_DIVIDE,
2370 /* Remainder of division of arithmetic values; analogous to:
2371 (EXPR_A) % (EXPR_B)
2372 in C. */
2373 GCC_JIT_BINARY_OP_MODULO,
2375 /* Bitwise AND; analogous to:
2376 (EXPR_A) & (EXPR_B)
2377 in C. */
2378 GCC_JIT_BINARY_OP_BITWISE_AND,
2380 /* Bitwise exclusive OR; analogous to:
2381 (EXPR_A) ^ (EXPR_B)
2382 in C. */
2383 GCC_JIT_BINARY_OP_BITWISE_XOR,
2385 /* Bitwise inclusive OR; analogous to:
2386 (EXPR_A) | (EXPR_B)
2387 in C. */
2388 GCC_JIT_BINARY_OP_BITWISE_OR,
2390 /* Logical AND; analogous to:
2391 (EXPR_A) && (EXPR_B)
2392 in C. */
2393 GCC_JIT_BINARY_OP_LOGICAL_AND,
2395 /* Logical OR; analogous to:
2396 (EXPR_A) || (EXPR_B)
2397 in C. */
2398 GCC_JIT_BINARY_OP_LOGICAL_OR,
2400 /* Left shift; analogous to:
2401 (EXPR_A) << (EXPR_B)
2402 in C. */
2403 GCC_JIT_BINARY_OP_LSHIFT,
2405 /* Right shift; analogous to:
2406 (EXPR_A) >> (EXPR_B)
2407 in C. */
2408 GCC_JIT_BINARY_OP_RSHIFT
2411 gcc_jit_rvalue *gcc_jit_context_new_binary_op(gcc_jit_context *ctxt,
2412 gcc_jit_location *loc,
2413 gcc_jit_binary_op op,
2414 gcc_jit_type *result_type,
2415 gcc_jit_rvalue *a, gcc_jit_rvalue *b);
2417 /* (Comparisons are treated as separate from "binary_op" to save
2418 you having to specify the result_type). */
2420 alias gcc_jit_comparison = uint;
2421 enum : gcc_jit_comparison
2423 /* (EXPR_A) == (EXPR_B). */
2424 GCC_JIT_COMPARISON_EQ,
2426 /* (EXPR_A) != (EXPR_B). */
2427 GCC_JIT_COMPARISON_NE,
2429 /* (EXPR_A) < (EXPR_B). */
2430 GCC_JIT_COMPARISON_LT,
2432 /* (EXPR_A) <=(EXPR_B). */
2433 GCC_JIT_COMPARISON_LE,
2435 /* (EXPR_A) > (EXPR_B). */
2436 GCC_JIT_COMPARISON_GT,
2438 /* (EXPR_A) >= (EXPR_B). */
2439 GCC_JIT_COMPARISON_GE
2442 gcc_jit_rvalue *gcc_jit_context_new_comparison(gcc_jit_context *ctxt,
2443 gcc_jit_location *loc,
2444 gcc_jit_comparison op,
2445 gcc_jit_rvalue *a, gcc_jit_rvalue *b);
2447 /* Function calls. */
2449 /* Call of a specific function. */
2450 gcc_jit_rvalue *gcc_jit_context_new_call(gcc_jit_context *ctxt,
2451 gcc_jit_location *loc,
2452 gcc_jit_function *func,
2453 int numargs , gcc_jit_rvalue **args);
2455 /* Call through a function pointer. */
2456 gcc_jit_rvalue *gcc_jit_context_new_call_through_ptr(gcc_jit_context *ctxt,
2457 gcc_jit_location *loc,
2458 gcc_jit_rvalue *fn_ptr,
2459 int numargs, gcc_jit_rvalue **args);
2461 /* Type-coercion.
2463 Currently only a limited set of conversions are possible:
2464 int <-> float
2465 int <-> bool */
2466 gcc_jit_rvalue *gcc_jit_context_new_cast(gcc_jit_context *ctxt,
2467 gcc_jit_location *loc,
2468 gcc_jit_rvalue *rvalue,
2469 gcc_jit_type *type);
2471 gcc_jit_lvalue *gcc_jit_context_new_array_access(gcc_jit_context *ctxt,
2472 gcc_jit_location *loc,
2473 gcc_jit_rvalue *ptr,
2474 gcc_jit_rvalue *index);
2476 /* Field access is provided separately for both lvalues and rvalues. */
2478 /* Accessing a field of an lvalue of struct type, analogous to:
2479 (EXPR).field = ...;
2480 in C. */
2481 gcc_jit_lvalue *gcc_jit_lvalue_access_field(gcc_jit_lvalue *struct_or_union,
2482 gcc_jit_location *loc,
2483 gcc_jit_field *field);
2485 /* Accessing a field of an rvalue of struct type, analogous to:
2486 (EXPR).field
2487 in C. */
2488 gcc_jit_rvalue *gcc_jit_rvalue_access_field(gcc_jit_rvalue *struct_or_union,
2489 gcc_jit_location *loc,
2490 gcc_jit_field *field);
2492 /* Accessing a field of an rvalue of pointer type, analogous to:
2493 (EXPR)->field
2494 in C, itself equivalent to (*EXPR).FIELD */
2495 gcc_jit_lvalue *gcc_jit_rvalue_dereference_field(gcc_jit_rvalue *ptr,
2496 gcc_jit_location *loc,
2497 gcc_jit_field *field);
2499 /* Dereferencing a pointer; analogous to:
2500 *(EXPR)
2502 gcc_jit_lvalue *gcc_jit_rvalue_dereference(gcc_jit_rvalue *rvalue,
2503 gcc_jit_location *loc);
2505 /* Taking the address of an lvalue; analogous to:
2506 &(EXPR)
2507 in C. */
2508 gcc_jit_rvalue *gcc_jit_lvalue_get_address(gcc_jit_lvalue *lvalue,
2509 gcc_jit_location *loc);
2511 gcc_jit_lvalue *gcc_jit_function_new_local(gcc_jit_function *func,
2512 gcc_jit_location *loc,
2513 gcc_jit_type *type,
2514 in char *name);
2516 /**********************************************************************
2517 Statement-creation.
2518 **********************************************************************/
2520 /* Add evaluation of an rvalue, discarding the result
2521 (e.g. a function call that "returns" void).
2523 This is equivalent to this C code:
2525 (void)expression;
2527 void gcc_jit_block_add_eval(gcc_jit_block *block,
2528 gcc_jit_location *loc,
2529 gcc_jit_rvalue *rvalue);
2531 /* Add evaluation of an rvalue, assigning the result to the given
2532 lvalue.
2534 This is roughly equivalent to this C code:
2536 lvalue = rvalue;
2538 void gcc_jit_block_add_assignment(gcc_jit_block *block,
2539 gcc_jit_location *loc,
2540 gcc_jit_lvalue *lvalue,
2541 gcc_jit_rvalue *rvalue);
2543 /* Add evaluation of an rvalue, using the result to modify an
2544 lvalue.
2546 This is analogous to "+=" and friends:
2548 lvalue += rvalue;
2549 lvalue *= rvalue;
2550 lvalue /= rvalue;
2551 etc */
2552 void gcc_jit_block_add_assignment_op(gcc_jit_block *block,
2553 gcc_jit_location *loc,
2554 gcc_jit_lvalue *lvalue,
2555 gcc_jit_binary_op op,
2556 gcc_jit_rvalue *rvalue);
2558 /* Add a no-op textual comment to the internal representation of the
2559 code. It will be optimized away, but will be visible in the dumps
2560 seen via
2561 GCC_JIT_BOOL_OPTION_DUMP_INITIAL_TREE
2563 GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE,
2564 and thus may be of use when debugging how your project's internal
2565 representation gets converted to the libgccjit IR. */
2566 void gcc_jit_block_add_comment(gcc_jit_block *block,
2567 gcc_jit_location *loc,
2568 in char *text);
2570 /* Terminate a block by adding evaluation of an rvalue, branching on the
2571 result to the appropriate successor block.
2573 This is roughly equivalent to this C code:
2575 if (boolval)
2576 goto on_true;
2577 else
2578 goto on_false;
2580 block, boolval, on_true, and on_false must be non-NULL. */
2581 void gcc_jit_block_end_with_conditional(gcc_jit_block *block,
2582 gcc_jit_location *loc,
2583 gcc_jit_rvalue *boolval,
2584 gcc_jit_block *on_true,
2585 gcc_jit_block *on_false);
2587 /* Terminate a block by adding a jump to the given target block.
2589 This is roughly equivalent to this C code:
2591 goto target;
2593 void gcc_jit_block_end_with_jump(gcc_jit_block *block,
2594 gcc_jit_location *loc,
2595 gcc_jit_block *target);
2597 /* Terminate a block by adding evaluation of an rvalue, returning the value.
2599 This is roughly equivalent to this C code:
2601 return expression;
2603 void gcc_jit_block_end_with_return(gcc_jit_block *block,
2604 gcc_jit_location *loc,
2605 gcc_jit_rvalue *rvalue);
2607 /* Terminate a block by adding a valueless return, for use within a function
2608 with "void" return type.
2610 This is equivalent to this C code:
2612 return;
2614 void gcc_jit_block_end_with_void_return(gcc_jit_block *block,
2615 gcc_jit_location *loc);
2617 /**********************************************************************
2618 Nested contexts.
2619 **********************************************************************/
2621 /* Given an existing JIT context, create a child context.
2623 The child inherits a copy of all option-settings from the parent.
2625 The child can reference objects created within the parent, but not
2626 vice-versa.
2628 The lifetime of the child context must be bounded by that of the
2629 parent: you should release a child context before releasing the parent
2630 context.
2632 If you use a function from a parent context within a child context,
2633 you have to compile the parent context before you can compile the
2634 child context, and the gcc_jit_result of the parent context must
2635 outlive the gcc_jit_result of the child context.
2637 This allows caching of shared initializations. For example, you could
2638 create types and declarations of global functions in a parent context
2639 once within a process, and then create child contexts whenever a
2640 function or loop becomes hot. Each such child context can be used for
2641 JIT-compiling just one function or loop, but can reference types
2642 and helper functions created within the parent context.
2644 Contexts can be arbitrarily nested, provided the above rules are
2645 followed, but it's probably not worth going above 2 or 3 levels, and
2646 there will likely be a performance hit for such nesting. */
2648 gcc_jit_context *gcc_jit_context_new_child_context(gcc_jit_context *parent_ctxt);