added "iv.dynstring"
[iv.d.git] / gccjit.d
blob538f474641bc5396325c9e631917b2ac4c1a1531
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, version 3 of the License ONLY.
10 /// This program is distributed in the hope that it will be useful,
11 /// but WITHOUT ANY WARRANTY; without even the implied warranty of
12 /// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 /// GNU General Public License for more details.
15 /// You should have received a copy of the GNU General Public License
16 /// along with this program. If not, see <http://www.gnu.org/licenses/>.
17 module iv.gccjit /*is aliced*/;
18 pragma(lib, "gccjit");
20 import iv.alice;
21 import std.conv : to;
22 import std.string : toStringz;
23 import std.traits : isIntegral, isSigned;
25 /// Errors within the API become D exceptions of this class.
26 final class JITError : Exception
28 @safe pure nothrow this(string msg, Throwable next = null)
30 super(msg, next);
33 @safe pure nothrow this(string msg, string file, usize line, Throwable next = null)
35 super(msg, file, line, next);
39 /// Class wrapper for gcc_jit_object.
40 /// All JITObject's are created within a JITContext, and are automatically
41 /// cleaned up when the context is released.
43 /// The class hierachy looks like this:
44 /// $(OL - JITObject
45 /// $(OL - JITLocation)
46 /// $(OL - JITType
47 /// $(OL - JITStruct))
48 /// $(OL - JITField)
49 /// $(OL - JITFunction)
50 /// $(OL - JITBlock)
51 /// $(OL - JITRValue
52 /// $(OL - JITLValue
53 /// $(OL - JITParam))))
54 class JITObject
56 /// Return the context this JITObject is within.
57 final JITContext getContext()
59 auto result = gcc_jit_object_get_context(this.m_inner_obj);
60 return new JITContext(result);
63 /// Get a human-readable description of this object.
64 override final string toString()
66 auto result = gcc_jit_object_get_debug_string(this.m_inner_obj);
67 return to!string(result);
70 protected:
71 // Constructors and getObject are hidden from public.
72 this()
74 this.m_inner_obj = null;
77 this(gcc_jit_object *obj)
79 if (!obj)
80 throw new JITError("Unknown error, got bad object");
81 this.m_inner_obj = obj;
84 final gcc_jit_object *getObject()
86 return this.m_inner_obj;
89 private:
90 // The actual gccjit object we interface with.
91 gcc_jit_object *m_inner_obj;
94 /// Class wrapper for gcc_jit_location.
95 /// A JITLocation encapsulates a source code locations, so that you can associate
96 /// locations in your language with statements in the JIT-compiled code.
97 class JITLocation : JITObject
99 ///
100 this()
102 super();
106 this(gcc_jit_location *loc)
108 super(gcc_jit_location_as_object(loc));
111 /// Returns the internal gcc_jit_location object.
112 final gcc_jit_location *getLocation()
114 // Manual downcast.
115 return cast(gcc_jit_location *)(this.getObject());
119 /// The top-level of the API is the JITContext class.
121 /// A JITContext instance encapsulates the state of a compilation.
122 /// It goes through two states.
123 /// Initial:
124 /// During which you can set up options on it, and add types,
125 /// functions and code, using the API below. Invoking compile
126 /// on it transitions it to the PostCompilation state.
127 /// PostCompilation:
128 /// When you can call JITContext.release to clean it up.
129 final class JITContext
132 this(bool acquire = true)
134 if (acquire)
135 this.m_inner_ctxt = gcc_jit_context_acquire();
136 else
137 this.m_inner_ctxt = null;
141 this(gcc_jit_context *context)
143 if (!context)
144 throw new JITError("Unknown error, got bad context");
145 this.m_inner_ctxt = context;
148 /// Acquire a JIT-compilation context.
149 static JITContext acquire()
151 return new JITContext(gcc_jit_context_acquire());
154 /// Release the context.
155 /// After this call, it's no longer valid to use this JITContext.
156 void release()
158 gcc_jit_context_release(this.m_inner_ctxt);
159 this.m_inner_ctxt = null;
162 /// Set a string option of the context; see JITStrOption for notes
163 /// on the options and their meanings.
164 /// Params:
165 /// opt = Which option to set.
166 /// value = The new value.
167 void setOption(JITStrOption opt, string value)
169 gcc_jit_context_set_str_option(this.m_inner_ctxt, opt, value.toStringz());
172 /// Set an integer option of the context; see JITIntOption for notes
173 /// on the options and their meanings.
174 /// Params:
175 /// opt = Which option to set.
176 /// value = The new value.
177 void setOption(JITIntOption opt, int value)
179 gcc_jit_context_set_int_option(this.m_inner_ctxt, opt, value);
182 /// Set a boolean option of the context; see JITBoolOption for notes
183 /// on the options and their meanings.
184 /// Params:
185 /// opt = Which option to set.
186 /// value = The new value.
187 void setOption(JITBoolOption opt, bool value)
189 gcc_jit_context_set_bool_option(this.m_inner_ctxt, opt, value);
192 /// Calls into GCC and runs the build. It can only be called once on a
193 /// given context.
194 /// Returns:
195 /// A wrapper around a .so file.
196 JITResult compile()
198 auto result = gcc_jit_context_compile(this.m_inner_ctxt);
199 if (!result)
200 throw new JITError(this.getFirstError());
201 return new JITResult(result);
204 /// Returns:
205 /// The first error message that occurred when compiling the context.
206 string getFirstError()
208 const char *err = gcc_jit_context_get_first_error(this.m_inner_ctxt);
209 if (err)
210 return to!string(err);
211 return null;
214 /// Dump a C-like representation describing what's been set up on the
215 /// context to file.
216 /// Params:
217 /// path = Location of file to write to.
218 /// update_locations = If true, then also write JITLocation information.
219 void dump(string path, bool update_locations)
221 gcc_jit_context_dump_to_file(this.m_inner_ctxt,
222 path.toStringz(),
223 update_locations);
226 /// Returns the internal gcc_jit_context object.
227 gcc_jit_context *getContext()
229 return this.m_inner_ctxt;
232 /// Build a JITType from one of the types in JITTypeKind.
233 JITType getType(JITTypeKind kind)
235 auto result = gcc_jit_context_get_type(this.m_inner_ctxt, kind);
236 return new JITType(result);
239 /// Build an integer type of a given size and signedness.
240 JITType getIntType(int num_bytes, bool is_signed)
242 auto result = gcc_jit_context_get_int_type(this.m_inner_ctxt,
243 num_bytes, is_signed);
244 return new JITType(result);
247 /// A way to map a specific int type, using the compiler to
248 /// get the details automatically e.g:
249 /// JITType type = getIntType!usize();
250 JITType getIntType(T)() if (isIntegral!T)
252 return this.getIntType(T.sizeof, isSigned!T);
255 /// Create a reference to a GCC builtin function.
256 JITFunction getBuiltinFunction(string name)
258 auto result = gcc_jit_context_get_builtin_function(this.m_inner_ctxt,
259 name.toStringz());
260 return new JITFunction(result);
263 /// Create a new child context of the given JITContext, inheriting a copy
264 /// of all option settings from the parent.
265 /// The returned JITContext can reference objects created within the
266 /// parent, but not vice-versa. The lifetime of the child context must be
267 /// bounded by that of the parent. You should release a child context
268 /// before releasing the parent context.
269 JITContext newChildContext()
271 auto result = gcc_jit_context_new_child_context(this.m_inner_ctxt);
272 if (!result)
273 throw new JITError("Unknown error creating child context");
274 return new JITContext(result);
277 /// Make a JITLocation representing a source location,
278 /// for use by the debugger.
279 /// Note:
280 /// You need to enable JITBoolOption.DEBUGINFO on the context
281 /// for these locations to actually be usable by the debugger.
282 JITLocation newLocation(string filename, int line, int column)
284 auto result = gcc_jit_context_new_location(this.m_inner_ctxt,
285 filename.toStringz(),
286 line, column);
287 return new JITLocation(result);
290 /// Given type "T", build a new array type of "T[N]".
291 JITType newArrayType(JITLocation loc, JITType type, int dims)
293 auto result = gcc_jit_context_new_array_type(this.m_inner_ctxt,
294 loc ? loc.getLocation() : null,
295 type.getType(), dims);
296 return new JITType(result);
299 /// Ditto
300 JITType newArrayType(JITType type, int dims)
302 return this.newArrayType(null, type, dims);
305 /// Ditto
306 JITType newArrayType(JITLocation loc, JITTypeKind kind, int dims)
308 return this.newArrayType(loc, this.getType(kind), dims);
311 /// Ditto
312 JITType newArrayType(JITTypeKind kind, int dims)
314 return this.newArrayType(null, this.getType(kind), dims);
317 /// Create a field, for use within a struct or union.
318 JITField newField(JITLocation loc, JITType type, string name)
320 auto result = gcc_jit_context_new_field(this.m_inner_ctxt,
321 loc ? loc.getLocation() : null,
322 type.getType(),
323 name.toStringz());
324 return new JITField(result);
327 /// Ditto
328 JITField newField(JITType type, string name)
330 return this.newField(null, type, name);
333 /// Ditto
334 JITField newField(JITLocation loc, JITTypeKind kind, string name)
336 return this.newField(loc, this.getType(kind), name);
339 /// Ditto
340 JITField newField(JITTypeKind kind, string name)
342 return this.newField(null, this.getType(kind), name);
345 /// Create a struct type from an array of fields.
346 JITStruct newStructType(JITLocation loc, string name, JITField[] fields...)
348 // Convert to an array of inner pointers.
349 gcc_jit_field*[] field_p = new gcc_jit_field*[fields.length];
350 foreach(i, field; fields)
351 field_p[i] = field.getField();
353 // Treat the array as being of the underlying pointers, relying on
354 // the wrapper type being such a pointer internally.
355 auto result = gcc_jit_context_new_struct_type(this.m_inner_ctxt,
356 loc ? loc.getLocation() : null,
357 name.toStringz(),
358 cast(int)fields.length,
359 field_p.ptr);
360 return new JITStruct(result);
363 /// Ditto
364 JITStruct newStructType(string name, JITField[] fields...)
366 return this.newStructType(null, name, fields);
369 /// Create an opaque struct type.
370 JITStruct newOpaqueStructType(JITLocation loc, string name)
372 auto result = gcc_jit_context_new_opaque_struct(this.m_inner_ctxt,
373 loc ? loc.getLocation() : null,
374 name.toStringz());
375 return new JITStruct(result);
378 /// Ditto
379 JITStruct newOpaqueStructType(string name)
381 return this.newOpaqueStructType(null, name);
384 /// Create a union type from an array of fields.
385 JITType newUnionType(JITLocation loc, string name, JITField[] fields...)
387 // Convert to an array of inner pointers.
388 gcc_jit_field*[] field_p = new gcc_jit_field*[fields.length];
389 foreach(i, field; fields)
390 field_p[i] = field.getField();
392 // Treat the array as being of the underlying pointers, relying on
393 // the wrapper type being such a pointer internally.
394 auto result = gcc_jit_context_new_union_type(this.m_inner_ctxt,
395 loc ? loc.getLocation() : null,
396 name.toStringz(),
397 cast(int)fields.length,
398 field_p.ptr);
399 return new JITType(result);
402 /// Ditto
403 JITType newUnionType(string name, JITField[] fields...)
405 return this.newUnionType(null, name, fields);
408 /// Create a function type.
409 JITType newFunctionType(JITLocation loc, JITType return_type,
410 bool is_variadic, JITType[] param_types...)
412 // Convert to an array of inner pointers.
413 gcc_jit_type*[] type_p = new gcc_jit_type*[param_types.length];
414 foreach(i, type; param_types)
415 type_p[i] = type.getType();
417 // Treat the array as being of the underlying pointers, relying on
418 // the wrapper type being such a pointer internally.
419 auto result = gcc_jit_context_new_function_ptr_type(this.m_inner_ctxt,
420 loc ? loc.getLocation() : null,
421 return_type.getType(),
422 cast(int)param_types.length,
423 type_p.ptr, is_variadic);
424 return new JITType(result);
427 /// Ditto
428 JITType newFunctionType(JITType return_type, bool is_variadic,
429 JITType[] param_types...)
431 return this.newFunctionType(null, return_type, is_variadic,
432 param_types);
435 /// Ditto
436 JITType newFunctionType(JITLocation loc, JITTypeKind return_kind,
437 bool is_variadic, JITType[] param_types...)
439 return this.newFunctionType(loc, this.getType(return_kind),
440 is_variadic, param_types);
443 /// Ditto
444 JITType newFunctionType(JITTypeKind return_kind, bool is_variadic,
445 JITType[] param_types...)
447 return this.newFunctionType(null, this.getType(return_kind),
448 is_variadic, param_types);
451 /// Create a function parameter.
452 JITParam newParam(JITLocation loc, JITType type, string name)
454 auto result = gcc_jit_context_new_param(this.m_inner_ctxt,
455 loc ? loc.getLocation() : null,
456 type.getType(),
457 name.toStringz());
458 return new JITParam(result);
461 /// Ditto
462 JITParam newParam(JITType type, string name)
464 return this.newParam(null, type, name);
467 /// Ditto
468 JITParam newParam(JITLocation loc, JITTypeKind kind, string name)
470 return this.newParam(loc, this.getType(kind), name);
473 /// Ditto
474 JITParam newParam(JITTypeKind kind, string name)
476 return this.newParam(null, this.getType(kind), name);
479 /// Create a function.
480 JITFunction newFunction(JITLocation loc, JITFunctionKind kind, JITType return_type,
481 string name, bool is_variadic, JITParam[] params...)
483 // Convert to an array of inner pointers.
484 gcc_jit_param*[] param_p = new gcc_jit_param*[params.length];
485 foreach(i, param; params)
486 param_p[i] = param.getParam();
488 // Treat the array as being of the underlying pointers, relying on
489 // the wrapper type being such a pointer internally.
490 auto result = gcc_jit_context_new_function(this.m_inner_ctxt,
491 loc ? loc.getLocation() : null,
492 kind, return_type.getType(),
493 name.toStringz(),
494 cast(int)params.length,
495 param_p.ptr, is_variadic);
496 return new JITFunction(result);
499 /// Ditto
500 JITFunction newFunction(JITFunctionKind kind, JITType return_type,
501 string name, bool is_variadic, JITParam[] params...)
503 return this.newFunction(null, kind, return_type, name, is_variadic, params);
506 /// Ditto
507 JITFunction newFunction(JITLocation loc, JITFunctionKind kind, JITTypeKind return_kind,
508 string name, bool is_variadic, JITParam[] params...)
510 return this.newFunction(loc, kind, this.getType(return_kind),
511 name, is_variadic, params);
514 /// Ditto
515 JITFunction newFunction(JITFunctionKind kind, JITTypeKind return_kind,
516 string name, bool is_variadic, JITParam[] params...)
518 return this.newFunction(null, kind, this.getType(return_kind),
519 name, is_variadic, params);
523 JITLValue newGlobal(JITLocation loc, JITGlobalKind global_kind,
524 JITType type, string name)
526 auto result = gcc_jit_context_new_global(this.m_inner_ctxt,
527 loc ? loc.getLocation() : null,
528 global_kind, type.getType(),
529 name.toStringz());
530 return new JITLValue(result);
533 /// Ditto
534 JITLValue newGlobal(JITGlobalKind global_kind, JITType type, string name)
536 return this.newGlobal(null, global_kind, type, name);
539 /// Ditto
540 JITLValue newGlobal(JITLocation loc, JITGlobalKind global_kind,
541 JITTypeKind kind, string name)
543 return this.newGlobal(loc, global_kind, this.getType(kind), name);
546 /// Ditto
547 JITLValue newGlobal(JITGlobalKind global_kind, JITTypeKind kind, string name)
549 return this.newGlobal(null, global_kind, this.getType(kind), name);
552 /// Given a JITType, which must be a numeric type, get an integer constant
553 /// as a JITRValue of that type.
554 JITRValue newRValue(JITType type, int value)
556 auto result = gcc_jit_context_new_rvalue_from_int(this.m_inner_ctxt,
557 type.getType(), value);
558 return new JITRValue(result);
561 /// Ditto
562 JITRValue newRValue(JITTypeKind kind, int value)
564 return newRValue(this.getType(kind), value);
567 /// Given a JITType, which must be a floating point type, get a floating
568 /// point constant as a JITRValue of that type.
569 JITRValue newRValue(JITType type, double value)
571 auto result = gcc_jit_context_new_rvalue_from_double(this.m_inner_ctxt,
572 type.getType(), value);
573 return new JITRValue(result);
576 /// Ditto
577 JITRValue newRValue(JITTypeKind kind, double value)
579 return newRValue(this.getType(kind), value);
582 /// Given a JITType, which must be a pointer type, and an address, get a
583 /// JITRValue representing that address as a pointer of that type.
584 JITRValue newRValue(JITType type, void *value)
586 auto result = gcc_jit_context_new_rvalue_from_ptr(this.m_inner_ctxt,
587 type.getType(), value);
588 return new JITRValue(result);
591 /// Ditto
592 JITRValue newRValue(JITTypeKind kind, void *value)
594 return newRValue(this.getType(kind), value);
597 /// Make a JITRValue for the given string literal value.
598 /// Params:
599 /// value = The string literal.
600 JITRValue newRValue(string value)
602 auto result = gcc_jit_context_new_string_literal(this.m_inner_ctxt,
603 value.toStringz());
604 return new JITRValue(result);
607 /// Given a JITType, which must be a numeric type, get the constant 0 as a
608 /// JITRValue of that type.
609 JITRValue zero(JITType type)
611 auto result = gcc_jit_context_zero(this.m_inner_ctxt, type.getType());
612 return new JITRValue(result);
615 /// Ditto
616 JITRValue zero(JITTypeKind kind)
618 return this.zero(this.getType(kind));
621 /// Given a JITType, which must be a numeric type, get the constant 1 as a
622 /// JITRValue of that type.
623 JITRValue one(JITType type)
625 auto result = gcc_jit_context_one(this.m_inner_ctxt, type.getType());
626 return new JITRValue(result);
629 /// Ditto
630 JITRValue one(JITTypeKind kind)
632 return this.one(this.getType(kind));
635 /// Given a JITType, which must be a pointer type, get a JITRValue
636 /// representing the NULL pointer of that type.
637 JITRValue nil(JITType type)
639 auto result = gcc_jit_context_null(this.m_inner_ctxt, type.getType());
640 return new JITRValue(result);
643 /// Ditto
644 JITRValue nil(JITTypeKind kind)
646 return this.nil(this.getType(kind));
649 /// Generic unary operations.
651 /// Make a JITRValue for the given unary operation.
652 /// Params:
653 /// loc = The source location, if any.
654 /// op = Which unary operation.
655 /// type = The type of the result.
656 /// a = The input expression.
657 JITRValue newUnaryOp(JITLocation loc, JITUnaryOp op, JITType type, JITRValue a)
659 auto result = gcc_jit_context_new_unary_op(this.m_inner_ctxt,
660 loc ? loc.getLocation() : null,
661 op, type.getType(),
662 a.getRValue());
663 return new JITRValue(result);
666 /// Ditto
667 JITRValue newUnaryOp(JITUnaryOp op, JITType type, JITRValue a)
669 return this.newUnaryOp(null, op, type, a);
672 /// Generic binary operations.
674 /// Make a JITRValue for the given binary operation.
675 /// Params:
676 /// loc = The source location, if any.
677 /// op = Which binary operation.
678 /// type = The type of the result.
679 /// a = The first input expression.
680 /// b = The second input expression.
681 JITRValue newBinaryOp(JITLocation loc, JITBinaryOp op,
682 JITType type, JITRValue a, JITRValue b)
684 auto result = gcc_jit_context_new_binary_op(this.m_inner_ctxt,
685 loc ? loc.getLocation() : null,
686 op, type.getType(),
687 a.getRValue(),
688 b.getRValue());
689 return new JITRValue(result);
692 /// Ditto
693 JITRValue newBinaryOp(JITBinaryOp op, JITType type, JITRValue a, JITRValue b)
695 return this.newBinaryOp(null, op, type, a, b);
698 /// Generic comparisons.
700 /// Make a JITRValue of boolean type for the given comparison.
701 /// Params:
702 /// loc = The source location, if any.
703 /// op = Which comparison.
704 /// a = The first input expression.
705 /// b = The second input expression.
706 JITRValue newComparison(JITLocation loc, JITComparison op,
707 JITRValue a, JITRValue b)
709 auto result = gcc_jit_context_new_comparison(this.m_inner_ctxt,
710 loc ? loc.getLocation() : null,
711 op, a.getRValue(),
712 b.getRValue());
713 return new JITRValue(result);
716 /// Ditto
717 JITRValue newComparison(JITComparison op, JITRValue a, JITRValue b)
719 return this.newComparison(null, op, a, b);
722 /// The most general way of creating a function call.
723 JITRValue newCall(JITLocation loc, JITFunction func, JITRValue[] args...)
725 // Convert to an array of inner pointers.
726 gcc_jit_rvalue*[] arg_p = new gcc_jit_rvalue*[args.length];
727 foreach(i, arg; args)
728 arg_p[i] = arg.getRValue();
730 // Treat the array as being of the underlying pointers, relying on
731 // the wrapper type being such a pointer internally.
732 auto result = gcc_jit_context_new_call(this.m_inner_ctxt,
733 loc ? loc.getLocation() : null,
734 func.getFunction(),
735 cast(int)args.length,
736 arg_p.ptr);
737 return new JITRValue(result);
740 /// Ditto
741 JITRValue newCall(JITFunction func, JITRValue[] args...)
743 return this.newCall(null, func, args);
746 /// Calling a function through a pointer.
747 JITRValue newCall(JITLocation loc, JITRValue ptr, JITRValue[] args...)
749 // Convert to an array of inner pointers.
750 gcc_jit_rvalue*[] arg_p = new gcc_jit_rvalue*[args.length];
751 foreach(i, arg; args)
752 arg_p[i] = arg.getRValue();
754 // Treat the array as being of the underlying pointers, relying on
755 // the wrapper type being such a pointer internally.
756 auto result = gcc_jit_context_new_call_through_ptr(this.m_inner_ctxt,
757 loc ? loc.getLocation() : null,
758 ptr.getRValue(),
759 cast(int)args.length,
760 arg_p.ptr);
761 return new JITRValue(result);
764 /// Ditto
765 JITRValue newCall(JITRValue ptr, JITRValue[] args...)
767 return this.newCall(null, ptr, args);
770 /// Type-coercion.
771 /// Currently only a limited set of conversions are possible.
772 /// int <=> float and int <=> bool.
773 JITRValue newCast(JITLocation loc, JITRValue expr, JITType type)
775 auto result = gcc_jit_context_new_cast(this.m_inner_ctxt,
776 loc ? loc.getLocation() : null,
777 expr.getRValue(), type.getType());
778 return new JITRValue(result);
781 /// Ditto
782 JITRValue newCast(JITRValue expr, JITType type)
784 return this.newCast(null, expr, type);
787 /// Ditto
788 JITRValue newCast(JITLocation loc, JITRValue expr, JITTypeKind kind)
790 return this.newCast(loc, expr, this.getType(kind));
793 /// Ditto
794 JITRValue newCast(JITRValue expr, JITTypeKind kind)
796 return this.newCast(null, expr, this.getType(kind));
799 /// Accessing an array or pointer through an index.
800 /// Params:
801 /// loc = The source location, if any.
802 /// ptr = The pointer or array.
803 /// index = The index within the array.
804 JITLValue newArrayAccess(JITLocation loc, JITRValue ptr, JITRValue index)
806 auto result = gcc_jit_context_new_array_access(this.m_inner_ctxt,
807 loc ? loc.getLocation() : null,
808 ptr.getRValue(), index.getRValue());
809 return new JITLValue(result);
812 /// Ditto
813 JITLValue newArrayAccess(JITRValue ptr, JITRValue index)
815 return this.newArrayAccess(null, ptr, index);
818 private:
819 gcc_jit_context *m_inner_ctxt;
822 /// Class wrapper for gcc_jit_field
823 class JITField : JITObject
826 this()
828 super();
832 this(gcc_jit_field *field)
834 super(gcc_jit_field_as_object(field));
837 /// Returns the internal gcc_jit_field object.
838 final gcc_jit_field *getField()
840 // Manual downcast.
841 return cast(gcc_jit_field *)(this.getObject());
845 /// Types can be created in several ways:
846 /// $(UL
847 /// $(LI Fundamental types can be accessed using JITContext.getType())
848 /// $(LI Derived types can be accessed by calling methods on an existing type.)
849 /// $(LI By creating structures via JITStruct.)
850 /// )
852 class JITType : JITObject
855 this()
857 super();
861 this(gcc_jit_type *type)
863 super(gcc_jit_type_as_object(type));
866 /// Returns the internal gcc_jit_type object.
867 final gcc_jit_type *getType()
869 // Manual downcast.
870 return cast(gcc_jit_type *)(this.getObject());
873 /// Given type T, get type T*.
874 final JITType pointerOf()
876 auto result = gcc_jit_type_get_pointer(this.getType());
877 return new JITType(result);
880 /// Given type T, get type const T.
881 final JITType constOf()
883 auto result = gcc_jit_type_get_const(this.getType());
884 return new JITType(result);
887 /// Given type T, get type volatile T.
888 final JITType volatileOf()
890 auto result = gcc_jit_type_get_volatile(this.getType());
891 return new JITType(result);
895 /// You can model C struct types by creating JITStruct and JITField
896 /// instances, in either order:
897 /// $(UL
898 /// $(LI By creating the fields, then the structure.)
899 /// $(LI By creating the structure, then populating it with fields,
900 /// typically to allow modelling self-referential structs.)
901 /// )
902 class JITStruct : JITType
905 this()
907 super(null);
911 this(gcc_jit_struct *agg)
913 super(gcc_jit_struct_as_type(agg));
916 /// Returns the internal gcc_jit_struct object.
917 final gcc_jit_struct *getStruct()
919 // Manual downcast.
920 return cast(gcc_jit_struct *)(this.getObject());
923 /// Populate the fields of a formerly-opaque struct type.
924 /// This can only be called once on a given struct type.
925 final void setFields(JITLocation loc, JITField[] fields...)
927 // Convert to an array of inner pointers.
928 gcc_jit_field*[] field_p = new gcc_jit_field*[fields.length];
929 foreach(i, field; fields)
930 field_p[i] = field.getField();
932 // Treat the array as being of the underlying pointers, relying on
933 // the wrapper type being such a pointer internally.
934 gcc_jit_struct_set_fields(this.getStruct(), loc ? loc.getLocation() : null,
935 cast(int)fields.length, field_p.ptr);
938 /// Ditto
939 final void setFields(JITField[] fields...)
941 this.setFields(null, fields);
945 /// Class wrapper for gcc_jit_function
946 class JITFunction : JITObject
949 this()
951 super();
955 this(gcc_jit_function *func)
957 if (!func)
958 throw new JITError("Unknown error, got bad function");
959 super(gcc_jit_function_as_object(func));
962 /// Returns the internal gcc_jit_function object.
963 final gcc_jit_function *getFunction()
965 // Manual downcast.
966 return cast(gcc_jit_function *)(this.getObject());
969 /// Dump function to dot file.
970 final void dump(string path)
972 gcc_jit_function_dump_to_dot(this.getFunction(), path.toStringz());
975 /// Get a specific param of a function by index.
976 final JITParam getParam(int index)
978 auto result = gcc_jit_function_get_param(this.getFunction(), index);
979 return new JITParam(result);
982 /// Create a new JITBlock.
983 /// The name can be null, or you can give it a meaningful name, which may
984 /// show up in dumps of the internal representation, and in error messages.
985 final JITBlock newBlock()
987 auto result = gcc_jit_function_new_block(this.getFunction(), null);
988 return new JITBlock(result);
991 /// Ditto
992 final JITBlock newBlock(string name)
994 auto result = gcc_jit_function_new_block(this.getFunction(),
995 name.toStringz());
996 return new JITBlock(result);
999 /// Create a new local variable.
1000 final JITLValue newLocal(JITLocation loc, JITType type, string name)
1002 auto result = gcc_jit_function_new_local(this.getFunction(),
1003 loc ? loc.getLocation() : null,
1004 type.getType(),
1005 name.toStringz());
1006 return new JITLValue(result);
1009 /// Ditto
1010 final JITLValue newLocal(JITType type, string name)
1012 return this.newLocal(null, type, name);
1017 /// Class wrapper for gcc_jit_block
1018 class JITBlock : JITObject
1021 this()
1023 super();
1027 this(gcc_jit_block *block)
1029 super(gcc_jit_block_as_object(block));
1032 /// Returns the internal gcc_jit_block object.
1033 final gcc_jit_block *getBlock()
1035 // Manual downcast.
1036 return cast(gcc_jit_block *)(this.getObject());
1039 /// Returns the JITFunction this JITBlock is within.
1040 final JITFunction getFunction()
1042 auto result = gcc_jit_block_get_function(this.getBlock());
1043 return new JITFunction(result);
1046 /// Add evaluation of an rvalue, discarding the result.
1047 final void addEval(JITLocation loc, JITRValue rvalue)
1049 gcc_jit_block_add_eval(this.getBlock(),
1050 loc ? loc.getLocation() : null,
1051 rvalue.getRValue());
1054 /// Ditto
1055 final void addEval(JITRValue rvalue)
1057 return this.addEval(null, rvalue);
1060 /// Add evaluation of an rvalue, assigning the result to the given lvalue.
1061 /// This is equivalent to "lvalue = rvalue".
1062 final void addAssignment(JITLocation loc, JITLValue lvalue, JITRValue rvalue)
1064 gcc_jit_block_add_assignment(this.getBlock(),
1065 loc ? loc.getLocation() : null,
1066 lvalue.getLValue(), rvalue.getRValue());
1069 /// Ditto
1070 final void addAssignment(JITLValue lvalue, JITRValue rvalue)
1072 return this.addAssignment(null, lvalue, rvalue);
1075 /// Add evaluation of an rvalue, using the result to modify an lvalue.
1076 /// This is equivalent to "lvalue op= rvalue".
1077 final void addAssignmentOp(JITLocation loc, JITLValue lvalue,
1078 JITBinaryOp op, JITRValue rvalue)
1080 gcc_jit_block_add_assignment_op(this.getBlock(),
1081 loc ? loc.getLocation() : null,
1082 lvalue.getLValue(), op, rvalue.getRValue());
1085 /// Ditto
1086 final void addAssignmentOp(JITLValue lvalue, JITBinaryOp op, JITRValue rvalue)
1088 return this.addAssignmentOp(null, lvalue, op, rvalue);
1091 /// A way to add a function call to the body of a function being
1092 /// defined, with various number of args.
1093 final JITRValue addCall(JITLocation loc, JITFunction func, JITRValue[] args...)
1095 JITRValue rv = this.getContext().newCall(loc, func, args);
1096 this.addEval(loc, rv);
1097 return rv;
1100 /// Ditto
1101 final JITRValue addCall(JITFunction func, JITRValue[] args...)
1103 return this.addCall(null, func, args);
1106 /// Add a no-op textual comment to the internal representation of the code.
1107 /// It will be optimized away, but visible in the dumps seens via
1108 /// JITBoolOption.DUMP_INITIAL_TREE and JITBoolOption.DUMP_INITIAL_GIMPLE.
1109 final void addComment(JITLocation loc, string text)
1111 gcc_jit_block_add_comment(this.getBlock(),
1112 loc ? loc.getLocation() : null,
1113 text.toStringz());
1116 /// Ditto
1117 final void addComment(string text)
1119 return this.addComment(null, text);
1122 /// Terminate a block by adding evaluation of an rvalue, branching on the
1123 /// result to the appropriate successor block.
1124 final void endWithConditional(JITLocation loc, JITRValue val,
1125 JITBlock on_true, JITBlock on_false)
1127 gcc_jit_block_end_with_conditional(this.getBlock(),
1128 loc ? loc.getLocation() : null,
1129 val.getRValue(),
1130 on_true.getBlock(),
1131 on_false.getBlock());
1134 /// Ditto
1135 final void endWithConditional(JITRValue val, JITBlock on_true, JITBlock on_false)
1137 return this.endWithConditional(null, val, on_true, on_false);
1140 /// Terminate a block by adding a jump to the given target block.
1141 /// This is equivalent to "goto target".
1142 final void endWithJump(JITLocation loc, JITBlock target)
1144 gcc_jit_block_end_with_jump(this.getBlock(),
1145 loc ? loc.getLocation() : null,
1146 target.getBlock());
1149 /// Ditto
1150 final void endWithJump(JITBlock target)
1152 return this.endWithJump(null, target);
1155 /// Terminate a block by adding evaluation of an rvalue, returning the value.
1156 /// This is equivalent to "return rvalue".
1157 final void endWithReturn(JITLocation loc, JITRValue rvalue)
1159 gcc_jit_block_end_with_return(this.getBlock(),
1160 loc ? loc.getLocation() : null,
1161 rvalue.getRValue());
1164 /// Ditto
1165 final void endWithReturn(JITRValue rvalue)
1167 return this.endWithReturn(null, rvalue);
1170 /// Terminate a block by adding a valueless return, for use within a
1171 /// function with "void" return type.
1172 /// This is equivalent to "return".
1173 final void endWithReturn(JITLocation loc = null)
1175 gcc_jit_block_end_with_void_return(this.getBlock(),
1176 loc ? loc.getLocation() : null);
1180 /// Class wrapper for gcc_jit_rvalue
1181 class JITRValue : JITObject
1184 this()
1186 super();
1190 this(gcc_jit_rvalue *rvalue)
1192 if (!rvalue)
1193 throw new JITError("Unknown error, got bad rvalue");
1194 super(gcc_jit_rvalue_as_object(rvalue));
1197 /// Returns the internal gcc_jit_rvalue object.
1198 final gcc_jit_rvalue *getRValue()
1200 // Manual downcast.
1201 return cast(gcc_jit_rvalue *)(this.getObject());
1204 /// Returns the JITType of the rvalue.
1205 final JITType getType()
1207 auto result = gcc_jit_rvalue_get_type(this.getRValue());
1208 return new JITType(result);
1211 /// Accessing a field of an rvalue of struct type.
1212 /// This is equivalent to "(value).field".
1213 JITRValue accessField(JITLocation loc, JITField field)
1215 auto result = gcc_jit_rvalue_access_field(this.getRValue(),
1216 loc ? loc.getLocation() : null,
1217 field.getField());
1218 return new JITRValue(result);
1221 /// Ditto
1222 JITRValue accessField(JITField field)
1224 return this.accessField(null, field);
1227 /// Accessing a field of an rvalue of pointer type.
1228 /// This is equivalent to "(*value).field".
1229 final JITLValue dereferenceField(JITLocation loc, JITField field)
1231 auto result = gcc_jit_rvalue_dereference_field(this.getRValue(),
1232 loc ? loc.getLocation() : null,
1233 field.getField());
1234 return new JITLValue(result);
1237 /// Ditto
1238 final JITLValue dereferenceField(JITField field)
1240 return this.dereferenceField(null, field);
1243 /// Dereferencing an rvalue of pointer type.
1244 /// This is equivalent to "*(value)".
1245 final JITLValue dereference(JITLocation loc = null)
1247 auto result = gcc_jit_rvalue_dereference(this.getRValue(),
1248 loc ? loc.getLocation() : null);
1249 return new JITLValue(result);
1252 /// Convert an rvalue to the given JITType. See JITContext.newCast for
1253 /// limitations.
1254 final JITRValue castTo(JITLocation loc, JITType type)
1256 return this.getContext().newCast(loc, this, type);
1259 /// Ditto
1260 final JITRValue castTo(JITType type)
1262 return this.castTo(null, type);
1265 /// Ditto
1266 final JITRValue castTo(JITLocation loc, JITTypeKind kind)
1268 return this.castTo(loc, this.getContext().getType(kind));
1271 /// Ditto
1272 final JITRValue castTo(JITTypeKind kind)
1274 return this.castTo(null, this.getContext().getType(kind));
1278 /// Class wrapper for gcc_jit_lvalue
1279 class JITLValue : JITRValue
1282 this()
1284 super();
1288 this(gcc_jit_lvalue *lvalue)
1290 if (!lvalue)
1291 throw new JITError("Unknown error, got bad lvalue");
1292 super(gcc_jit_lvalue_as_rvalue(lvalue));
1295 /// Returns the internal gcc_jit_lvalue object.
1296 final gcc_jit_lvalue *getLValue()
1298 // Manual downcast.
1299 return cast(gcc_jit_lvalue *)(this.getObject());
1302 /// Accessing a field of an lvalue of struct type.
1303 /// This is equivalent to "(value).field = ...".
1304 override JITLValue accessField(JITLocation loc, JITField field)
1306 auto result = gcc_jit_lvalue_access_field(this.getLValue(),
1307 loc ? loc.getLocation() : null,
1308 field.getField());
1309 return new JITLValue(result);
1312 /// Ditto
1313 override JITLValue accessField(JITField field)
1315 return this.accessField(null, field);
1318 /// Taking the address of an lvalue.
1319 /// This is equivalent to "&(value)".
1320 final JITRValue getAddress(JITLocation loc = null)
1322 auto result = gcc_jit_lvalue_get_address(this.getLValue(),
1323 loc ? loc.getLocation() : null);
1324 return new JITRValue(result);
1328 /// Class wrapper for gcc_jit_param
1329 class JITParam : JITLValue
1332 this()
1334 super();
1338 this(gcc_jit_param *param)
1340 if (!param)
1341 throw new JITError("Unknown error, got bad param");
1342 super(gcc_jit_param_as_lvalue(param));
1345 /// Returns the internal gcc_jit_param object.
1346 final gcc_jit_param *getParam()
1348 // Manual downcast.
1349 return cast(gcc_jit_param *)(this.getObject());
1353 /// Class wrapper for gcc_jit_result
1354 final class JITResult
1357 this()
1359 this.m_inner_result = null;
1363 this(gcc_jit_result *result)
1365 if (!result)
1366 throw new JITError("Unknown error, got bad result");
1367 this.m_inner_result = result;
1370 /// Returns the internal gcc_jit_result object.
1371 gcc_jit_result *getResult()
1373 return this.m_inner_result;
1376 /// Locate a given function within the built machine code.
1377 /// This will need to be cast to a function pointer of the correct type
1378 /// before it can be called.
1379 void *getCode(string name)
1381 return gcc_jit_result_get_code(this.getResult(), name.toStringz());
1384 /// Locate a given global within the built machine code.
1385 /// It must have been created using JITGlobalKind.EXPORTED.
1386 /// This returns is a pointer to the global.
1387 void *getGlobal(string name)
1389 return gcc_jit_result_get_global(this.getResult(), name.toStringz());
1392 /// Once we're done with the code, this unloads the built .so file.
1393 /// After this call, it's no longer valid to use this JITResult.
1394 void release()
1396 gcc_jit_result_release(this.getResult());
1399 private:
1400 gcc_jit_result *m_inner_result;
1403 /// Kinds of function.
1404 enum JITFunctionKind : gcc_jit_function_kind
1406 /// Function is defined by the client code and visible by name
1407 /// outside of the JIT.
1408 EXPORTED = GCC_JIT_FUNCTION_EXPORTED,
1409 /// Function is defined by the client code, but is invisible
1410 /// outside of the JIT.
1411 INTERNAL = GCC_JIT_FUNCTION_INTERNAL,
1412 /// Function is not defined by the client code; we're merely
1413 /// referring to it.
1414 IMPORTED = GCC_JIT_FUNCTION_IMPORTED,
1415 /// Function is only ever inlined into other functions, and is
1416 /// invisible outside of the JIT.
1417 ALWAYS_INLINE = GCC_JIT_FUNCTION_ALWAYS_INLINE,
1420 /// Kinds of global.
1421 enum JITGlobalKind : gcc_jit_global_kind
1423 /// Global is defined by the client code and visible by name
1424 /// outside of this JIT context.
1425 EXPORTED = GCC_JIT_GLOBAL_EXPORTED,
1426 /// Global is defined by the client code, but is invisible
1427 /// outside of this JIT context. Analogous to a "static" global.
1428 INTERNAL = GCC_JIT_GLOBAL_INTERNAL,
1429 /// Global is not defined by the client code; we're merely
1430 /// referring to it. Analogous to using an "extern" global.
1431 IMPORTED = GCC_JIT_GLOBAL_IMPORTED,
1434 /// Standard types.
1435 enum JITTypeKind : gcc_jit_types
1437 /// C's void type.
1438 VOID = GCC_JIT_TYPE_VOID,
1440 /// C's void* type.
1441 VOID_PTR = GCC_JIT_TYPE_VOID_PTR,
1443 /// C++'s bool type.
1444 BOOL = GCC_JIT_TYPE_BOOL,
1446 /// C's char type.
1447 CHAR = GCC_JIT_TYPE_CHAR,
1449 /// C's signed char type.
1450 SIGNED_CHAR = GCC_JIT_TYPE_SIGNED_CHAR,
1452 /// C's unsigned char type.
1453 UNSIGNED_CHAR = GCC_JIT_TYPE_UNSIGNED_CHAR,
1455 /// C's short type.
1456 SHORT = GCC_JIT_TYPE_SHORT,
1458 /// C's unsigned short type.
1459 UNSIGNED_SHORT = GCC_JIT_TYPE_UNSIGNED_SHORT,
1461 /// C's int type.
1462 INT = GCC_JIT_TYPE_INT,
1464 /// C's unsigned int type.
1465 UNSIGNED_INT = GCC_JIT_TYPE_UNSIGNED_INT,
1467 /// C's long type.
1468 LONG = GCC_JIT_TYPE_LONG,
1470 /// C's unsigned long type.
1471 UNSIGNED_LONG = GCC_JIT_TYPE_UNSIGNED_LONG,
1473 /// C99's long long type.
1474 LONG_LONG = GCC_JIT_TYPE_LONG_LONG,
1476 /// C99's unsigned long long type.
1477 UNSIGNED_LONG_LONG = GCC_JIT_TYPE_UNSIGNED_LONG_LONG,
1479 /// Single precision floating point type.
1480 FLOAT = GCC_JIT_TYPE_FLOAT,
1482 /// Double precision floating point type.
1483 DOUBLE = GCC_JIT_TYPE_DOUBLE,
1485 /// Largest supported floating point type.
1486 LONG_DOUBLE = GCC_JIT_TYPE_LONG_DOUBLE,
1488 /// C's const char* type.
1489 CONST_CHAR_PTR = GCC_JIT_TYPE_CONST_CHAR_PTR,
1491 /// C's usize type.
1492 SIZE_T = GCC_JIT_TYPE_SIZE_T,
1494 /// C's FILE* type.
1495 FILE_PTR = GCC_JIT_TYPE_FILE_PTR,
1497 /// Single precision complex float type.
1498 COMPLEX_FLOAT = GCC_JIT_TYPE_COMPLEX_FLOAT,
1500 /// Double precision complex float type.
1501 COMPLEX_DOUBLE = GCC_JIT_TYPE_COMPLEX_DOUBLE,
1503 /// Largest supported complex float type.
1504 COMPLEX_LONG_DOUBLE = GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE,
1507 /// Kinds of unary ops.
1508 enum JITUnaryOp : gcc_jit_unary_op
1510 /// Negate an arithmetic value.
1511 /// This is equivalent to "-(value)".
1512 MINUS = GCC_JIT_UNARY_OP_MINUS,
1513 /// Bitwise negation of an integer value (one's complement).
1514 /// This is equivalent to "~(value)".
1515 BITWISE_NEGATE = GCC_JIT_UNARY_OP_BITWISE_NEGATE,
1516 /// Logical negation of an arithmetic or pointer value.
1517 /// This is equivalent to "!(value)".
1518 LOGICAL_NEGATE = GCC_JIT_UNARY_OP_LOGICAL_NEGATE,
1521 /// Kinds of binary ops.
1522 enum JITBinaryOp : gcc_jit_binary_op
1524 /// Addition of arithmetic values.
1525 /// This is equivalent to "(a) + (b)".
1526 PLUS = GCC_JIT_BINARY_OP_PLUS,
1527 /// Subtraction of arithmetic values.
1528 /// This is equivalent to "(a) - (b)".
1529 MINUS = GCC_JIT_BINARY_OP_MINUS,
1530 /// Multiplication of a pair of arithmetic values.
1531 /// This is equivalent to "(a) * (b)".
1532 MULT = GCC_JIT_BINARY_OP_MULT,
1533 /// Quotient of division of arithmetic values.
1534 /// This is equivalent to "(a) / (b)".
1535 DIVIDE = GCC_JIT_BINARY_OP_DIVIDE,
1536 /// Remainder of division of arithmetic values.
1537 /// This is equivalent to "(a) % (b)".
1538 MODULO = GCC_JIT_BINARY_OP_MODULO,
1539 /// Bitwise AND.
1540 /// This is equivalent to "(a) & (b)".
1541 BITWISE_AND = GCC_JIT_BINARY_OP_BITWISE_AND,
1542 /// Bitwise exclusive OR.
1543 /// This is equivalent to "(a) ^ (b)".
1544 BITWISE_XOR = GCC_JIT_BINARY_OP_BITWISE_XOR,
1545 /// Bitwise inclusive OR.
1546 /// This is equivalent to "(a) | (b)".
1547 BITWISE_OR = GCC_JIT_BINARY_OP_BITWISE_OR,
1548 /// Logical AND.
1549 /// This is equivalent to "(a) && (b)".
1550 LOGICAL_AND = GCC_JIT_BINARY_OP_LOGICAL_AND,
1551 /// Logical OR.
1552 /// This is equivalent to "(a) || (b)".
1553 LOGICAL_OR = GCC_JIT_BINARY_OP_LOGICAL_OR,
1554 /// Left shift.
1555 /// This is equivalent to "(a) << (b)".
1556 LSHIFT = GCC_JIT_BINARY_OP_LSHIFT,
1557 /// Right shift.
1558 /// This is equivalent to "(a) >> (b)".
1559 RSHIFT = GCC_JIT_BINARY_OP_RSHIFT,
1562 /// Kinds of comparison.
1563 enum JITComparison : gcc_jit_comparison
1565 /// This is equivalent to "(a) == (b)".
1566 EQ = GCC_JIT_COMPARISON_EQ,
1567 /// This is equivalent to "(a) != (b)".
1568 NE = GCC_JIT_COMPARISON_NE,
1569 /// This is equivalent to "(a) < (b)".
1570 LT = GCC_JIT_COMPARISON_LT,
1571 /// This is equivalent to "(a) <= (b)".
1572 LE = GCC_JIT_COMPARISON_LE,
1573 /// This is equivalent to "(a) > (b)".
1574 GT = GCC_JIT_COMPARISON_GT,
1575 /// This is equivalent to "(a) >= (b)".
1576 GE = GCC_JIT_COMPARISON_GE,
1579 /// String options
1580 enum JITStrOption : gcc_jit_str_option
1582 /// The name of the program, for use as a prefix when printing error
1583 /// messages to stderr. If None, or default, "libgccjit.so" is used.
1584 PROGNAME = GCC_JIT_STR_OPTION_PROGNAME,
1587 /// Integer options
1588 enum JITIntOption : gcc_jit_int_option
1590 /// How much to optimize the code.
1592 /// Valid values are 0-3, corresponding to GCC's command-line options
1593 /// -O0 through -O3.
1595 /// The default value is 0 (unoptimized).
1596 OPTIMIZATION_LEVEL = GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL,
1599 /// Boolean options
1600 enum JITBoolOption : gcc_jit_bool_option
1602 /// If true, JITContext.compile() will attempt to do the right thing
1603 /// so that if you attach a debugger to the process, it will be able
1604 /// to inspect variables and step through your code.
1606 /// Note that you can’t step through code unless you set up source
1607 /// location information for the code (by creating and passing in
1608 /// JITLocation instances).
1609 DEBUGINFO = GCC_JIT_BOOL_OPTION_DEBUGINFO,
1611 /// If true, JITContext.compile() will dump its initial "tree"
1612 /// representation of your code to stderr, before any optimizations.
1613 DUMP_INITIAL_TREE = GCC_JIT_BOOL_OPTION_DUMP_INITIAL_TREE,
1615 /// If true, JITContext.compile() will dump its initial "gimple"
1616 /// representation of your code to stderr, before any optimizations
1617 /// are performed. The dump resembles C code.
1618 DUMP_INITIAL_GIMPLE = GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE,
1620 /// If true, JITContext.compile() will dump the final generated code
1621 /// to stderr, in the form of assembly language.
1622 DUMP_GENERATED_CODE = GCC_JIT_BOOL_OPTION_DUMP_GENERATED_CODE,
1624 /// If true, JITContext.compile() will print information to stderr
1625 /// on the actions it is performing, followed by a profile showing
1626 /// the time taken and memory usage of each phase.
1627 DUMP_SUMMARY = GCC_JIT_BOOL_OPTION_DUMP_SUMMARY,
1629 /// If true, JITContext.compile() will dump copious amounts of
1630 /// information on what it’s doing to various files within a
1631 /// temporary directory. Use JITBoolOption.KEEP_INTERMEDIATES
1632 /// to see the results. The files are intended to be human-readable,
1633 /// but the exact files and their formats are subject to change.
1634 DUMP_EVERYTHING = GCC_JIT_BOOL_OPTION_DUMP_EVERYTHING,
1636 /// If true, libgccjit will aggressively run its garbage collector,
1637 /// to shake out bugs (greatly slowing down the compile). This is
1638 /// likely to only be of interest to developers of the library.
1639 SELFCHECK_GC = GCC_JIT_BOOL_OPTION_SELFCHECK_GC,
1641 /// If true, the JITContext will not clean up intermediate files
1642 /// written to the filesystem, and will display their location on
1643 /// stderr.
1644 KEEP_INTERMEDIATES = GCC_JIT_BOOL_OPTION_KEEP_INTERMEDIATES,
1649 /* A pure C API to enable client code to embed GCC as a JIT-compiler.
1651 This file has been modified from the libgccjit.h header to work with
1652 the D compiler. The original file is part of the GCC distribution
1653 and is licensed under the following terms.
1655 Copyright (C) 2013-2015 Free Software Foundation, Inc.
1657 This program is free software: you can redistribute it and/or modify
1658 it under the terms of the GNU General Public License as published by
1659 the Free Software Foundation, version 3 of the License ONLY.
1661 This program is distributed in the hope that it will be useful,
1662 but WITHOUT ANY WARRANTY; without even the implied warranty of
1663 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1664 GNU General Public License for more details.
1666 You should have received a copy of the GNU General Public License
1667 along with this program. If not, see <http://www.gnu.org/licenses/>.
1670 import core.stdc.stdio;
1672 extern(C):
1674 /**********************************************************************
1675 Data structures.
1676 **********************************************************************/
1677 /* All structs within the API are opaque. */
1679 /* A gcc_jit_context encapsulates the state of a compilation.
1680 You can set up options on it, and add types, functions and code, using
1681 the API below.
1683 Invoking gcc_jit_context_compile on it gives you a gcc_jit_result *
1684 (or NULL), representing in-memory machine code.
1686 You can call gcc_jit_context_compile repeatedly on one context, giving
1687 multiple independent results.
1689 Similarly, you can call gcc_jit_context_compile_to_file on a context
1690 to compile to disk.
1692 Eventually you can call gcc_jit_context_release to clean up the
1693 context; any in-memory results created from it are still usable, and
1694 should be cleaned up via gcc_jit_result_release. */
1695 struct gcc_jit_context;
1697 /* A gcc_jit_result encapsulates the result of an in-memory compilation. */
1698 struct gcc_jit_result;
1700 /* An object created within a context. Such objects are automatically
1701 cleaned up when the context is released.
1703 The class hierarchy looks like this:
1705 +- gcc_jit_object
1706 +- gcc_jit_location
1707 +- gcc_jit_type
1708 +- gcc_jit_struct
1709 +- gcc_jit_field
1710 +- gcc_jit_function
1711 +- gcc_jit_block
1712 +- gcc_jit_rvalue
1713 +- gcc_jit_lvalue
1714 +- gcc_jit_param
1716 struct gcc_jit_object;
1718 /* A gcc_jit_location encapsulates a source code location, so that
1719 you can (optionally) associate locations in your language with
1720 statements in the JIT-compiled code, allowing the debugger to
1721 single-step through your language.
1723 Note that to do so, you also need to enable
1724 GCC_JIT_BOOL_OPTION_DEBUGINFO
1725 on the gcc_jit_context.
1727 gcc_jit_location instances are optional; you can always pass
1728 NULL. */
1729 struct gcc_jit_location;
1731 /* A gcc_jit_type encapsulates a type e.g. "int" or a "struct foo*". */
1732 struct gcc_jit_type;
1734 /* A gcc_jit_field encapsulates a field within a struct; it is used
1735 when creating a struct type (using gcc_jit_context_new_struct_type).
1736 Fields cannot be shared between structs. */
1737 struct gcc_jit_field;
1739 /* A gcc_jit_struct encapsulates a struct type, either one that we have
1740 the layout for, or an opaque type. */
1741 struct gcc_jit_struct;
1743 /* A gcc_jit_function encapsulates a function: either one that you're
1744 creating yourself, or a reference to one that you're dynamically
1745 linking to within the rest of the process. */
1746 struct gcc_jit_function;
1748 /* A gcc_jit_block encapsulates a "basic block" of statements within a
1749 function (i.e. with one entry point and one exit point).
1751 Every block within a function must be terminated with a conditional,
1752 a branch, or a return.
1754 The blocks within a function form a directed graph.
1756 The entrypoint to the function is the first block created within
1759 All of the blocks in a function must be reachable via some path from
1760 the first block.
1762 It's OK to have more than one "return" from a function (i.e. multiple
1763 blocks that terminate by returning). */
1764 struct gcc_jit_block;
1766 /* A gcc_jit_rvalue is an expression within your code, with some type. */
1767 struct gcc_jit_rvalue;
1769 /* A gcc_jit_lvalue is a storage location within your code (e.g. a
1770 variable, a parameter, etc). It is also a gcc_jit_rvalue; use
1771 gcc_jit_lvalue_as_rvalue to cast. */
1772 struct gcc_jit_lvalue;
1774 /* A gcc_jit_param is a function parameter, used when creating a
1775 gcc_jit_function. It is also a gcc_jit_lvalue (and thus also an
1776 rvalue); use gcc_jit_param_as_lvalue to convert. */
1777 struct gcc_jit_param;
1779 /* Acquire a JIT-compilation context. */
1780 gcc_jit_context *gcc_jit_context_acquire();
1782 /* Release the context. After this call, it's no longer valid to use
1783 the ctxt. */
1784 void gcc_jit_context_release(gcc_jit_context *ctxt);
1786 /* Options taking string values. */
1787 alias gcc_jit_str_option = uint;
1788 enum : gcc_jit_str_option
1790 /* The name of the program, for use as a prefix when printing error
1791 messages to stderr. If NULL, or default, "libgccjit.so" is used. */
1792 GCC_JIT_STR_OPTION_PROGNAME,
1794 GCC_JIT_NUM_STR_OPTIONS
1797 /* Options taking int values. */
1798 alias gcc_jit_int_option = uint;
1799 enum : gcc_jit_int_option
1801 /* How much to optimize the code.
1802 Valid values are 0-3, corresponding to GCC's command-line options
1803 -O0 through -O3.
1805 The default value is 0 (unoptimized). */
1806 GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL,
1808 GCC_JIT_NUM_INT_OPTIONS
1811 /* Options taking boolean values.
1812 These all default to "false". */
1813 alias gcc_jit_bool_option = uint;
1814 enum : gcc_jit_bool_option
1816 /* If true, gcc_jit_context_compile will attempt to do the right
1817 thing so that if you attach a debugger to the process, it will
1818 be able to inspect variables and step through your code.
1820 Note that you can't step through code unless you set up source
1821 location information for the code (by creating and passing in
1822 gcc_jit_location instances). */
1823 GCC_JIT_BOOL_OPTION_DEBUGINFO,
1825 /* If true, gcc_jit_context_compile will dump its initial "tree"
1826 representation of your code to stderr (before any
1827 optimizations). */
1828 GCC_JIT_BOOL_OPTION_DUMP_INITIAL_TREE,
1830 /* If true, gcc_jit_context_compile will dump the "gimple"
1831 representation of your code to stderr, before any optimizations
1832 are performed. The dump resembles C code. */
1833 GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE,
1835 /* If true, gcc_jit_context_compile will dump the final
1836 generated code to stderr, in the form of assembly language. */
1837 GCC_JIT_BOOL_OPTION_DUMP_GENERATED_CODE,
1839 /* If true, gcc_jit_context_compile will print information to stderr
1840 on the actions it is performing, followed by a profile showing
1841 the time taken and memory usage of each phase.
1843 GCC_JIT_BOOL_OPTION_DUMP_SUMMARY,
1845 /* If true, gcc_jit_context_compile will dump copious
1846 amount of information on what it's doing to various
1847 files within a temporary directory. Use
1848 GCC_JIT_BOOL_OPTION_KEEP_INTERMEDIATES (see below) to
1849 see the results. The files are intended to be human-readable,
1850 but the exact files and their formats are subject to change.
1852 GCC_JIT_BOOL_OPTION_DUMP_EVERYTHING,
1854 /* If true, libgccjit will aggressively run its garbage collector, to
1855 shake out bugs (greatly slowing down the compile). This is likely
1856 to only be of interest to developers *of* the library. It is
1857 used when running the selftest suite. */
1858 GCC_JIT_BOOL_OPTION_SELFCHECK_GC,
1860 /* If true, gcc_jit_context_release will not clean up
1861 intermediate files written to the filesystem, and will display
1862 their location on stderr. */
1863 GCC_JIT_BOOL_OPTION_KEEP_INTERMEDIATES,
1865 GCC_JIT_NUM_BOOL_OPTIONS
1868 /* Set a string option on the given context.
1870 The context directly stores the (const char *), so the passed string
1871 must outlive the context. */
1872 void gcc_jit_context_set_str_option(gcc_jit_context *ctxt,
1873 gcc_jit_str_option opt,
1874 in char *value);
1876 /* Set an int option on the given context. */
1877 void gcc_jit_context_set_int_option(gcc_jit_context *ctxt,
1878 gcc_jit_int_option opt,
1879 int value);
1881 /* Set a boolean option on the given context.
1883 Zero is "false" (the default), non-zero is "true". */
1884 void gcc_jit_context_set_bool_option(gcc_jit_context *ctxt,
1885 gcc_jit_bool_option opt,
1886 int value);
1888 /* Compile the context to in-memory machine code.
1890 This can be called more that once on a given context,
1891 although any errors that occur will block further compilation. */
1893 gcc_jit_result *gcc_jit_context_compile(gcc_jit_context *ctxt);
1895 /* Kinds of ahead-of-time compilation, for use with
1896 gcc_jit_context_compile_to_file. */
1898 alias gcc_jit_output_kind = uint;
1899 enum : gcc_jit_output_kind
1901 /* Compile the context to an assembler file. */
1902 GCC_JIT_OUTPUT_KIND_ASSEMBLER,
1904 /* Compile the context to an object file. */
1905 GCC_JIT_OUTPUT_KIND_OBJECT_FILE,
1907 /* Compile the context to a dynamic library. */
1908 GCC_JIT_OUTPUT_KIND_DYNAMIC_LIBRARY,
1910 /* Compile the context to an executable. */
1911 GCC_JIT_OUTPUT_KIND_EXECUTABLE
1914 /* Compile the context to a file of the given kind.
1916 This can be called more that once on a given context,
1917 although any errors that occur will block further compilation. */
1919 void gcc_jit_context_compile_to_file(gcc_jit_context *ctxt,
1920 gcc_jit_output_kind output_kind,
1921 in char *output_path);
1923 /* To help with debugging: dump a C-like representation to the given path,
1924 describing what's been set up on the context.
1926 If "update_locations" is true, then also set up gcc_jit_location
1927 information throughout the context, pointing at the dump file as if it
1928 were a source file. This may be of use in conjunction with
1929 GCC_JIT_BOOL_OPTION_DEBUGINFO to allow stepping through the code in a
1930 debugger. */
1931 void gcc_jit_context_dump_to_file(gcc_jit_context *ctxt,
1932 in char *path,
1933 int update_locations);
1935 /* To help with debugging; enable ongoing logging of the context's
1936 activity to the given FILE *.
1938 The caller remains responsible for closing "logfile".
1940 Params "flags" and "verbosity" are reserved for future use, and
1941 must both be 0 for now. */
1942 void gcc_jit_context_set_logfile(gcc_jit_context *ctxt,
1943 FILE *logfile,
1944 int flags,
1945 int verbosity);
1947 /* To be called after any API call, this gives the first error message
1948 that occurred on the context.
1950 The returned string is valid for the rest of the lifetime of the
1951 context.
1953 If no errors occurred, this will be NULL. */
1954 const(char) *gcc_jit_context_get_first_error(gcc_jit_context *ctxt);
1956 /* To be called after any API call, this gives the last error message
1957 that occurred on the context.
1959 If no errors occurred, this will be NULL.
1961 If non-NULL, the returned string is only guaranteed to be valid until
1962 the next call to libgccjit relating to this context. */
1963 const(char) *gcc_jit_context_get_last_error(gcc_jit_context *ctxt);
1965 /* Locate a given function within the built machine code.
1966 This will need to be cast to a function pointer of the
1967 correct type before it can be called. */
1968 void *gcc_jit_result_get_code(gcc_jit_result *result,
1969 in char *funcname);
1971 /* Locate a given global within the built machine code.
1972 It must have been created using GCC_JIT_GLOBAL_EXPORTED.
1973 This is a ptr to the global, so e.g. for an int this is an int *. */
1974 void *gcc_jit_result_get_global (gcc_jit_result *result,
1975 in char *name);
1977 /* Once we're done with the code, this unloads the built .so file.
1978 This cleans up the result; after calling this, it's no longer
1979 valid to use the result. */
1980 void gcc_jit_result_release(gcc_jit_result *result);
1983 /**********************************************************************
1984 Functions for creating "contextual" objects.
1986 All objects created by these functions share the lifetime of the context
1987 they are created within, and are automatically cleaned up for you when
1988 you call gcc_jit_context_release on the context.
1990 Note that this means you can't use references to them after you've
1991 released their context.
1993 All (const char *) string arguments passed to these functions are
1994 copied, so you don't need to keep them around. Note that this *isn't*
1995 the case for other parts of the API.
1997 You create code by adding a sequence of statements to blocks.
1998 **********************************************************************/
2000 /**********************************************************************
2001 The base class of "contextual" object.
2002 **********************************************************************/
2003 /* Which context is "obj" within? */
2004 gcc_jit_context *gcc_jit_object_get_context(gcc_jit_object *obj);
2006 /* Get a human-readable description of this object.
2007 The string buffer is created the first time this is called on a given
2008 object, and persists until the object's context is released. */
2009 const(char) *gcc_jit_object_get_debug_string(gcc_jit_object *obj);
2011 /**********************************************************************
2012 Debugging information.
2013 **********************************************************************/
2015 /* Creating source code locations for use by the debugger.
2016 Line and column numbers are 1-based. */
2017 gcc_jit_location *gcc_jit_context_new_location(gcc_jit_context *ctxt,
2018 in char *filename,
2019 int line,
2020 int column);
2022 /* Upcasting from location to object. */
2023 gcc_jit_object *gcc_jit_location_as_object(gcc_jit_location *loc);
2026 /**********************************************************************
2027 Types.
2028 **********************************************************************/
2030 /* Upcasting from type to object. */
2031 gcc_jit_object *gcc_jit_type_as_object(gcc_jit_type *type);
2033 /* Access to specific types. */
2034 alias gcc_jit_types = uint;
2035 enum : gcc_jit_types
2037 /* C's "void" type. */
2038 GCC_JIT_TYPE_VOID,
2040 /* "void *". */
2041 GCC_JIT_TYPE_VOID_PTR,
2043 /* C++'s bool type; also C99's "_Bool" type, aka "bool" if using
2044 stdbool.h. */
2045 GCC_JIT_TYPE_BOOL,
2047 /* Various integer types. */
2049 /* C's "char" (of some signedness) and the variants where the
2050 signedness is specified. */
2051 GCC_JIT_TYPE_CHAR,
2052 GCC_JIT_TYPE_SIGNED_CHAR,
2053 GCC_JIT_TYPE_UNSIGNED_CHAR,
2055 /* C's "short" and "unsigned short". */
2056 GCC_JIT_TYPE_SHORT, /* signed */
2057 GCC_JIT_TYPE_UNSIGNED_SHORT,
2059 /* C's "int" and "unsigned int". */
2060 GCC_JIT_TYPE_INT, /* signed */
2061 GCC_JIT_TYPE_UNSIGNED_INT,
2063 /* C's "long" and "unsigned long". */
2064 GCC_JIT_TYPE_LONG, /* signed */
2065 GCC_JIT_TYPE_UNSIGNED_LONG,
2067 /* C99's "long long" and "unsigned long long". */
2068 GCC_JIT_TYPE_LONG_LONG, /* signed */
2069 GCC_JIT_TYPE_UNSIGNED_LONG_LONG,
2071 /* Floating-point types */
2073 GCC_JIT_TYPE_FLOAT,
2074 GCC_JIT_TYPE_DOUBLE,
2075 GCC_JIT_TYPE_LONG_DOUBLE,
2077 /* C type: (const char *). */
2078 GCC_JIT_TYPE_CONST_CHAR_PTR,
2080 /* The C "usize" type. */
2081 GCC_JIT_TYPE_SIZE_T,
2083 /* C type: (FILE *) */
2084 GCC_JIT_TYPE_FILE_PTR,
2086 /* Complex numbers. */
2087 GCC_JIT_TYPE_COMPLEX_FLOAT,
2088 GCC_JIT_TYPE_COMPLEX_DOUBLE,
2089 GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE
2092 gcc_jit_type *gcc_jit_context_get_type(gcc_jit_context *ctxt,
2093 gcc_jit_types type_);
2095 gcc_jit_type *gcc_jit_context_get_int_type(gcc_jit_context *ctxt,
2096 int num_bytes, int is_signed);
2098 /* Constructing new types. */
2100 /* Given type "T", get type "T*". */
2101 gcc_jit_type *gcc_jit_type_get_pointer(gcc_jit_type *type);
2103 /* Given type "T", get type "const T". */
2104 gcc_jit_type *gcc_jit_type_get_const(gcc_jit_type *type);
2106 /* Given type "T", get type "volatile T". */
2107 gcc_jit_type *gcc_jit_type_get_volatile(gcc_jit_type *type);
2109 /* Given type "T", get type "T[N]" (for a constant N). */
2110 gcc_jit_type *gcc_jit_context_new_array_type(gcc_jit_context *ctxt,
2111 gcc_jit_location *loc,
2112 gcc_jit_type *element_type,
2113 int num_elements);
2115 /* Struct-handling. */
2116 gcc_jit_field *gcc_jit_context_new_field(gcc_jit_context *ctxt,
2117 gcc_jit_location *loc,
2118 gcc_jit_type *type,
2119 in char *name);
2121 /* Upcasting from field to object. */
2122 gcc_jit_object *gcc_jit_field_as_object(gcc_jit_field *field);
2124 /* Create a struct type from an array of fields. */
2125 gcc_jit_struct *gcc_jit_context_new_struct_type(gcc_jit_context *ctxt,
2126 gcc_jit_location *loc,
2127 in char *name,
2128 int num_fields,
2129 gcc_jit_field **fields);
2132 /* Create an opaque struct type. */
2133 gcc_jit_struct *gcc_jit_context_new_opaque_struct(gcc_jit_context *ctxt,
2134 gcc_jit_location *loc,
2135 in char *name);
2137 /* Upcast a struct to a type. */
2138 gcc_jit_type *gcc_jit_struct_as_type(gcc_jit_struct *struct_type);
2140 /* Populating the fields of a formerly-opaque struct type.
2141 This can only be called once on a given struct type. */
2142 void gcc_jit_struct_set_fields(gcc_jit_struct *struct_type,
2143 gcc_jit_location *loc,
2144 int num_fields,
2145 gcc_jit_field **fields);
2147 /* Unions work similarly to structs. */
2148 gcc_jit_type *gcc_jit_context_new_union_type(gcc_jit_context *ctxt,
2149 gcc_jit_location *loc,
2150 in char *name,
2151 int num_fields,
2152 gcc_jit_field **fields);
2154 /* Function pointers. */
2155 gcc_jit_type *gcc_jit_context_new_function_ptr_type(gcc_jit_context *ctxt,
2156 gcc_jit_location *loc,
2157 gcc_jit_type *return_type,
2158 int num_params,
2159 gcc_jit_type **param_types,
2160 int is_variadic);
2163 /**********************************************************************
2164 Constructing functions.
2165 **********************************************************************/
2166 /* Create a function param. */
2167 gcc_jit_param *gcc_jit_context_new_param(gcc_jit_context *ctxt,
2168 gcc_jit_location *loc,
2169 gcc_jit_type *type,
2170 in char *name);
2172 /* Upcasting from param to object. */
2173 gcc_jit_object *gcc_jit_param_as_object(gcc_jit_param *param);
2175 /* Upcasting from param to lvalue. */
2176 gcc_jit_lvalue *gcc_jit_param_as_lvalue(gcc_jit_param *param);
2178 /* Upcasting from param to rvalue. */
2179 gcc_jit_rvalue *gcc_jit_param_as_rvalue(gcc_jit_param *param);
2181 /* Kinds of function. */
2182 alias gcc_jit_function_kind = uint;
2183 enum : gcc_jit_function_kind
2185 /* Function is defined by the client code and visible
2186 by name outside of the JIT. */
2187 GCC_JIT_FUNCTION_EXPORTED,
2189 /* Function is defined by the client code, but is invisible
2190 outside of the JIT. Analogous to a "static" function. */
2191 GCC_JIT_FUNCTION_INTERNAL,
2193 /* Function is not defined by the client code; we're merely
2194 referring to it. Analogous to using an "extern" function from a
2195 header file. */
2196 GCC_JIT_FUNCTION_IMPORTED,
2198 /* Function is only ever inlined into other functions, and is
2199 invisible outside of the JIT.
2201 Analogous to prefixing with "inline" and adding
2202 __attribute__((always_inline)).
2204 Inlining will only occur when the optimization level is
2205 above 0; when optimization is off, this is essentially the
2206 same as GCC_JIT_FUNCTION_INTERNAL. */
2207 GCC_JIT_FUNCTION_ALWAYS_INLINE
2210 /* Create a function. */
2211 gcc_jit_function *gcc_jit_context_new_function(gcc_jit_context *ctxt,
2212 gcc_jit_location *loc,
2213 gcc_jit_function_kind kind,
2214 gcc_jit_type *return_type,
2215 in char *name,
2216 int num_params,
2217 gcc_jit_param **params,
2218 int is_variadic);
2220 /* Create a reference to a builtin function (sometimes called intrinsic functions). */
2221 gcc_jit_function *gcc_jit_context_get_builtin_function(gcc_jit_context *ctxt,
2222 in char *name);
2224 /* Upcasting from function to object. */
2225 gcc_jit_object *gcc_jit_function_as_object(gcc_jit_function *func);
2227 /* Get a specific param of a function by index. */
2228 gcc_jit_param *gcc_jit_function_get_param(gcc_jit_function *func, int index);
2230 /* Emit the function in graphviz format. */
2231 void gcc_jit_function_dump_to_dot(gcc_jit_function *func,
2232 in char *path);
2234 /* Create a block.
2236 The name can be NULL, or you can give it a meaningful name, which
2237 may show up in dumps of the internal representation, and in error
2238 messages. */
2239 gcc_jit_block *gcc_jit_function_new_block(gcc_jit_function *func,
2240 in char *name);
2242 /* Upcasting from block to object. */
2243 gcc_jit_object *gcc_jit_block_as_object(gcc_jit_block *block);
2245 /* Which function is this block within? */
2246 gcc_jit_function *gcc_jit_block_get_function(gcc_jit_block *block);
2248 /**********************************************************************
2249 lvalues, rvalues and expressions.
2250 **********************************************************************/
2251 alias gcc_jit_global_kind = uint;
2252 enum : gcc_jit_global_kind
2254 /* Global is defined by the client code and visible
2255 by name outside of this JIT context via gcc_jit_result_get_global. */
2256 GCC_JIT_GLOBAL_EXPORTED,
2258 /* Global is defined by the client code, but is invisible
2259 outside of this JIT context. Analogous to a "static" global. */
2260 GCC_JIT_GLOBAL_INTERNAL,
2262 /* Global is not defined by the client code; we're merely
2263 referring to it. Analogous to using an "extern" global from a
2264 header file. */
2265 GCC_JIT_GLOBAL_IMPORTED
2268 gcc_jit_lvalue *gcc_jit_context_new_global(gcc_jit_context *ctxt,
2269 gcc_jit_location *loc,
2270 gcc_jit_global_kind kind,
2271 gcc_jit_type *type,
2272 in char *name);
2274 /* Upcasting. */
2275 gcc_jit_object *gcc_jit_lvalue_as_object(gcc_jit_lvalue *lvalue);
2277 gcc_jit_rvalue *gcc_jit_lvalue_as_rvalue(gcc_jit_lvalue *lvalue);
2279 gcc_jit_object *gcc_jit_rvalue_as_object(gcc_jit_rvalue *rvalue);
2281 gcc_jit_type *gcc_jit_rvalue_get_type(gcc_jit_rvalue *rvalue);
2283 /* Integer constants. */
2284 gcc_jit_rvalue *gcc_jit_context_new_rvalue_from_int(gcc_jit_context *ctxt,
2285 gcc_jit_type *numeric_type,
2286 int value);
2288 gcc_jit_rvalue *gcc_jit_context_new_rvalue_from_long(gcc_jit_context *ctxt,
2289 gcc_jit_type *numeric_type,
2290 long value);
2292 gcc_jit_rvalue *gcc_jit_context_zero(gcc_jit_context *ctxt,
2293 gcc_jit_type *numeric_type);
2295 gcc_jit_rvalue *gcc_jit_context_one(gcc_jit_context *ctxt,
2296 gcc_jit_type *numeric_type);
2298 /* Floating-point constants. */
2299 gcc_jit_rvalue *gcc_jit_context_new_rvalue_from_double(gcc_jit_context *ctxt,
2300 gcc_jit_type *numeric_type,
2301 double value);
2303 /* Pointers. */
2304 gcc_jit_rvalue *gcc_jit_context_new_rvalue_from_ptr(gcc_jit_context *ctxt,
2305 gcc_jit_type *pointer_type,
2306 void *value);
2308 gcc_jit_rvalue *gcc_jit_context_null(gcc_jit_context *ctxt,
2309 gcc_jit_type *pointer_type);
2311 /* String literals. */
2312 gcc_jit_rvalue *gcc_jit_context_new_string_literal(gcc_jit_context *ctxt,
2313 in char *value);
2315 alias gcc_jit_unary_op = uint;
2316 enum : gcc_jit_unary_op
2318 /* Negate an arithmetic value; analogous to:
2319 -(EXPR)
2320 in C. */
2321 GCC_JIT_UNARY_OP_MINUS,
2323 /* Bitwise negation of an integer value (one's complement); analogous
2325 ~(EXPR)
2326 in C. */
2327 GCC_JIT_UNARY_OP_BITWISE_NEGATE,
2329 /* Logical negation of an arithmetic or pointer value; analogous to:
2330 !(EXPR)
2331 in C. */
2332 GCC_JIT_UNARY_OP_LOGICAL_NEGATE
2335 gcc_jit_rvalue *gcc_jit_context_new_unary_op(gcc_jit_context *ctxt,
2336 gcc_jit_location *loc,
2337 gcc_jit_unary_op op,
2338 gcc_jit_type *result_type,
2339 gcc_jit_rvalue *rvalue);
2341 alias gcc_jit_binary_op = uint;
2342 enum : gcc_jit_binary_op
2344 /* Addition of arithmetic values; analogous to:
2345 (EXPR_A) + (EXPR_B)
2346 in C.
2347 For pointer addition, use gcc_jit_context_new_array_access. */
2348 GCC_JIT_BINARY_OP_PLUS,
2350 /* Subtraction of arithmetic values; analogous to:
2351 (EXPR_A) - (EXPR_B)
2352 in C. */
2353 GCC_JIT_BINARY_OP_MINUS,
2355 /* Multiplication of a pair of arithmetic values; analogous to:
2356 (EXPR_A) * (EXPR_B)
2357 in C. */
2358 GCC_JIT_BINARY_OP_MULT,
2360 /* Quotient of division of arithmetic values; analogous to:
2361 (EXPR_A) / (EXPR_B)
2362 in C.
2363 The result type affects the kind of division: if the result type is
2364 integer-based, then the result is truncated towards zero, whereas
2365 a floating-point result type indicates floating-point division. */
2366 GCC_JIT_BINARY_OP_DIVIDE,
2368 /* Remainder of division of arithmetic values; analogous to:
2369 (EXPR_A) % (EXPR_B)
2370 in C. */
2371 GCC_JIT_BINARY_OP_MODULO,
2373 /* Bitwise AND; analogous to:
2374 (EXPR_A) & (EXPR_B)
2375 in C. */
2376 GCC_JIT_BINARY_OP_BITWISE_AND,
2378 /* Bitwise exclusive OR; analogous to:
2379 (EXPR_A) ^ (EXPR_B)
2380 in C. */
2381 GCC_JIT_BINARY_OP_BITWISE_XOR,
2383 /* Bitwise inclusive OR; analogous to:
2384 (EXPR_A) | (EXPR_B)
2385 in C. */
2386 GCC_JIT_BINARY_OP_BITWISE_OR,
2388 /* Logical AND; analogous to:
2389 (EXPR_A) && (EXPR_B)
2390 in C. */
2391 GCC_JIT_BINARY_OP_LOGICAL_AND,
2393 /* Logical OR; analogous to:
2394 (EXPR_A) || (EXPR_B)
2395 in C. */
2396 GCC_JIT_BINARY_OP_LOGICAL_OR,
2398 /* Left shift; analogous to:
2399 (EXPR_A) << (EXPR_B)
2400 in C. */
2401 GCC_JIT_BINARY_OP_LSHIFT,
2403 /* Right shift; analogous to:
2404 (EXPR_A) >> (EXPR_B)
2405 in C. */
2406 GCC_JIT_BINARY_OP_RSHIFT
2409 gcc_jit_rvalue *gcc_jit_context_new_binary_op(gcc_jit_context *ctxt,
2410 gcc_jit_location *loc,
2411 gcc_jit_binary_op op,
2412 gcc_jit_type *result_type,
2413 gcc_jit_rvalue *a, gcc_jit_rvalue *b);
2415 /* (Comparisons are treated as separate from "binary_op" to save
2416 you having to specify the result_type). */
2418 alias gcc_jit_comparison = uint;
2419 enum : gcc_jit_comparison
2421 /* (EXPR_A) == (EXPR_B). */
2422 GCC_JIT_COMPARISON_EQ,
2424 /* (EXPR_A) != (EXPR_B). */
2425 GCC_JIT_COMPARISON_NE,
2427 /* (EXPR_A) < (EXPR_B). */
2428 GCC_JIT_COMPARISON_LT,
2430 /* (EXPR_A) <=(EXPR_B). */
2431 GCC_JIT_COMPARISON_LE,
2433 /* (EXPR_A) > (EXPR_B). */
2434 GCC_JIT_COMPARISON_GT,
2436 /* (EXPR_A) >= (EXPR_B). */
2437 GCC_JIT_COMPARISON_GE
2440 gcc_jit_rvalue *gcc_jit_context_new_comparison(gcc_jit_context *ctxt,
2441 gcc_jit_location *loc,
2442 gcc_jit_comparison op,
2443 gcc_jit_rvalue *a, gcc_jit_rvalue *b);
2445 /* Function calls. */
2447 /* Call of a specific function. */
2448 gcc_jit_rvalue *gcc_jit_context_new_call(gcc_jit_context *ctxt,
2449 gcc_jit_location *loc,
2450 gcc_jit_function *func,
2451 int numargs , gcc_jit_rvalue **args);
2453 /* Call through a function pointer. */
2454 gcc_jit_rvalue *gcc_jit_context_new_call_through_ptr(gcc_jit_context *ctxt,
2455 gcc_jit_location *loc,
2456 gcc_jit_rvalue *fn_ptr,
2457 int numargs, gcc_jit_rvalue **args);
2459 /* Type-coercion.
2461 Currently only a limited set of conversions are possible:
2462 int <-> float
2463 int <-> bool */
2464 gcc_jit_rvalue *gcc_jit_context_new_cast(gcc_jit_context *ctxt,
2465 gcc_jit_location *loc,
2466 gcc_jit_rvalue *rvalue,
2467 gcc_jit_type *type);
2469 gcc_jit_lvalue *gcc_jit_context_new_array_access(gcc_jit_context *ctxt,
2470 gcc_jit_location *loc,
2471 gcc_jit_rvalue *ptr,
2472 gcc_jit_rvalue *index);
2474 /* Field access is provided separately for both lvalues and rvalues. */
2476 /* Accessing a field of an lvalue of struct type, analogous to:
2477 (EXPR).field = ...;
2478 in C. */
2479 gcc_jit_lvalue *gcc_jit_lvalue_access_field(gcc_jit_lvalue *struct_or_union,
2480 gcc_jit_location *loc,
2481 gcc_jit_field *field);
2483 /* Accessing a field of an rvalue of struct type, analogous to:
2484 (EXPR).field
2485 in C. */
2486 gcc_jit_rvalue *gcc_jit_rvalue_access_field(gcc_jit_rvalue *struct_or_union,
2487 gcc_jit_location *loc,
2488 gcc_jit_field *field);
2490 /* Accessing a field of an rvalue of pointer type, analogous to:
2491 (EXPR)->field
2492 in C, itself equivalent to (*EXPR).FIELD */
2493 gcc_jit_lvalue *gcc_jit_rvalue_dereference_field(gcc_jit_rvalue *ptr,
2494 gcc_jit_location *loc,
2495 gcc_jit_field *field);
2497 /* Dereferencing a pointer; analogous to:
2498 *(EXPR)
2500 gcc_jit_lvalue *gcc_jit_rvalue_dereference(gcc_jit_rvalue *rvalue,
2501 gcc_jit_location *loc);
2503 /* Taking the address of an lvalue; analogous to:
2504 &(EXPR)
2505 in C. */
2506 gcc_jit_rvalue *gcc_jit_lvalue_get_address(gcc_jit_lvalue *lvalue,
2507 gcc_jit_location *loc);
2509 gcc_jit_lvalue *gcc_jit_function_new_local(gcc_jit_function *func,
2510 gcc_jit_location *loc,
2511 gcc_jit_type *type,
2512 in char *name);
2514 /**********************************************************************
2515 Statement-creation.
2516 **********************************************************************/
2518 /* Add evaluation of an rvalue, discarding the result
2519 (e.g. a function call that "returns" void).
2521 This is equivalent to this C code:
2523 (void)expression;
2525 void gcc_jit_block_add_eval(gcc_jit_block *block,
2526 gcc_jit_location *loc,
2527 gcc_jit_rvalue *rvalue);
2529 /* Add evaluation of an rvalue, assigning the result to the given
2530 lvalue.
2532 This is roughly equivalent to this C code:
2534 lvalue = rvalue;
2536 void gcc_jit_block_add_assignment(gcc_jit_block *block,
2537 gcc_jit_location *loc,
2538 gcc_jit_lvalue *lvalue,
2539 gcc_jit_rvalue *rvalue);
2541 /* Add evaluation of an rvalue, using the result to modify an
2542 lvalue.
2544 This is analogous to "+=" and friends:
2546 lvalue += rvalue;
2547 lvalue *= rvalue;
2548 lvalue /= rvalue;
2549 etc */
2550 void gcc_jit_block_add_assignment_op(gcc_jit_block *block,
2551 gcc_jit_location *loc,
2552 gcc_jit_lvalue *lvalue,
2553 gcc_jit_binary_op op,
2554 gcc_jit_rvalue *rvalue);
2556 /* Add a no-op textual comment to the internal representation of the
2557 code. It will be optimized away, but will be visible in the dumps
2558 seen via
2559 GCC_JIT_BOOL_OPTION_DUMP_INITIAL_TREE
2561 GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE,
2562 and thus may be of use when debugging how your project's internal
2563 representation gets converted to the libgccjit IR. */
2564 void gcc_jit_block_add_comment(gcc_jit_block *block,
2565 gcc_jit_location *loc,
2566 in char *text);
2568 /* Terminate a block by adding evaluation of an rvalue, branching on the
2569 result to the appropriate successor block.
2571 This is roughly equivalent to this C code:
2573 if (boolval)
2574 goto on_true;
2575 else
2576 goto on_false;
2578 block, boolval, on_true, and on_false must be non-NULL. */
2579 void gcc_jit_block_end_with_conditional(gcc_jit_block *block,
2580 gcc_jit_location *loc,
2581 gcc_jit_rvalue *boolval,
2582 gcc_jit_block *on_true,
2583 gcc_jit_block *on_false);
2585 /* Terminate a block by adding a jump to the given target block.
2587 This is roughly equivalent to this C code:
2589 goto target;
2591 void gcc_jit_block_end_with_jump(gcc_jit_block *block,
2592 gcc_jit_location *loc,
2593 gcc_jit_block *target);
2595 /* Terminate a block by adding evaluation of an rvalue, returning the value.
2597 This is roughly equivalent to this C code:
2599 return expression;
2601 void gcc_jit_block_end_with_return(gcc_jit_block *block,
2602 gcc_jit_location *loc,
2603 gcc_jit_rvalue *rvalue);
2605 /* Terminate a block by adding a valueless return, for use within a function
2606 with "void" return type.
2608 This is equivalent to this C code:
2610 return;
2612 void gcc_jit_block_end_with_void_return(gcc_jit_block *block,
2613 gcc_jit_location *loc);
2615 /**********************************************************************
2616 Nested contexts.
2617 **********************************************************************/
2619 /* Given an existing JIT context, create a child context.
2621 The child inherits a copy of all option-settings from the parent.
2623 The child can reference objects created within the parent, but not
2624 vice-versa.
2626 The lifetime of the child context must be bounded by that of the
2627 parent: you should release a child context before releasing the parent
2628 context.
2630 If you use a function from a parent context within a child context,
2631 you have to compile the parent context before you can compile the
2632 child context, and the gcc_jit_result of the parent context must
2633 outlive the gcc_jit_result of the child context.
2635 This allows caching of shared initializations. For example, you could
2636 create types and declarations of global functions in a parent context
2637 once within a process, and then create child contexts whenever a
2638 function or loop becomes hot. Each such child context can be used for
2639 JIT-compiling just one function or loop, but can reference types
2640 and helper functions created within the parent context.
2642 Contexts can be arbitrarily nested, provided the above rules are
2643 followed, but it's probably not worth going above 2 or 3 levels, and
2644 there will likely be a performance hit for such nesting. */
2646 gcc_jit_context *gcc_jit_context_new_child_context(gcc_jit_context *parent_ctxt);