1 
2 // Sample client code for C API
3 
4 module gccjitd.examples.capi;
5 
6 import gccjit.c;
7 
8 void main()
9 {
10     // Memory mangement is simple: all objects created are associated with a gcc_jit_context,
11     // and get automatically cleaned up when the context is released.
12     gcc_jit_context *ctxt = gcc_jit_context_acquire();
13 
14     // Let's inject the equivalent of:
15     //  extern(C) int printf(in char *format, ...);
16     //  void hello_fn(in char *name)
17     //  {
18     //      printf("hello %s\n", name);
19     //  }
20     // into the context.
21     gcc_jit_type *const_char_ptr_type = gcc_jit_context_get_type(ctxt, GCC_JIT_TYPE_CONST_CHAR_PTR);
22     gcc_jit_param *param_format =
23         gcc_jit_context_new_param(ctxt, null, const_char_ptr_type, "format");
24     gcc_jit_function *printf_func =
25         gcc_jit_context_new_function(ctxt, null, GCC_JIT_FUNCTION_IMPORTED,
26                                      gcc_jit_context_get_type(ctxt, GCC_JIT_TYPE_INT),
27                                      "printf", 1, &param_format, 1);
28 
29     gcc_jit_param *param_name =
30         gcc_jit_context_new_param(ctxt, null, const_char_ptr_type, "name");
31     gcc_jit_function *func =
32         gcc_jit_context_new_function(ctxt, null, GCC_JIT_FUNCTION_EXPORTED,
33                                      gcc_jit_context_get_type(ctxt, GCC_JIT_TYPE_VOID),
34                                      "hello_fn", 1, &param_name, 0);
35 
36     gcc_jit_rvalue *args[2];
37     args[0] = gcc_jit_context_new_string_literal(ctxt, "hello %s\n");
38     args[1] = gcc_jit_param_as_rvalue(param_name);
39 
40     gcc_jit_block *block = gcc_jit_function_new_block(func, "initial");
41     gcc_jit_block_add_eval(block, null,
42                            gcc_jit_context_new_call(ctxt, null, printf_func, 2, args.ptr));
43     gcc_jit_block_end_with_void_return(block, null);
44 
45     // OK, we're done populating the context.
46     // The next line actually calls into GCC and runs the build, all
47     // in a mutex for now, getting make a result object.
48     // The result is actually a wrapper around a DSO.
49     gcc_jit_result *result = gcc_jit_context_compile(ctxt);
50 
51     // Now that we have result, we're done with ctxt.  Releasing it will
52     // automatically clean up all of the objects created within it.
53     gcc_jit_context_release(ctxt);
54 
55     // Look up a generated function by name, getting a void* back
56     // from the result object (pointing to the machine code), and
57     // cast it to the appropriate type for the function:
58     alias hello_fn_type = void function(in char *);
59     auto hello_fn = cast(hello_fn_type)gcc_jit_result_get_code(result, "hello_fn");
60 
61     // We can now call the machine code:
62     hello_fn("world");
63 
64     // Presumably we'd call it more than once.
65     // Once we're done with the code, this unloads the built DSO:
66     gcc_jit_result_release(result);
67 }
68