Metaprogramming Build Options

To get the build options for the compiler, create a workspace with the function compiler_create_workspace and call get_build_options on the workspace created under compiler_create_workspace. Here is an example build function that demonstrates this:

#import "Basic";
#import "Compiler";

build :: () {
  w := compiler_create_workspace();
  if !w {
    print("Workspace creation failed.\n");
    return;
  }
  target_options := get_build_options(w);
  //...other code
}

The Build_Options struct contains many build options such as enabling/disabling array bounds check, setting the optimization level, switching the backend between LLVM and x64, changing the executable name, and setting the OS target.

Simple Build Options for highly optimized code

This snippet creates a highly optimized build. Optimized builds take a long time, but are around twice as fast as an unoptimized build. The build options included do things such as setting the compiler backend to LLVM, disabling array bounds check, disabling number cast checking, and enabling tail call recursion optimization.

set_optimization_level(target_options, 2, 0); // same as clang -O2

Target Build Options

The output type for target_options can be specified between no output, executable, dynamic library, and static library. By default, the output type is an executable.

target_options.output_type = .NO_OUTPUT;       // specifies no output for the compiler
target_options.output_type = .EXECUTABLE;      // specifies executable as an output for the compiler
target_options.output_type = .DYNAMIC_LIBRARY; // specifies output to be a dynamic library
target_options.output_type = .STATIC_LIBRARY;  // specifies output to be a static library
target_options.output_type = .OBJECT_FILE;     // specifies output to be an object file

Optimization levels can be toggled between debug and release.

target_options.optimization_level = .DEBUG;   // specifies the optimization level to be .DEBUG
target_options.optimization_level = .RELEASE; // specifies the optimization level to be .RELEASE

The different backend options can be toggled between -x64 and llvm as follows:

target_options.backend = .X64;  // specifies the x64 backend
target_options.backend = .LLVM; // specifies the llvm backend

Array bounds check can be changed through the array_bounds_check field.

target_options.array_bounds_check = .OFF; // turns off array bounds check
target_options.array_bounds_check = .ON;  // turns on array bounds check
target_options.array_bounds_check = .ALWAYS;

The build options for the llvm and x64 backends can be be set through the x64_options and llvm_options fields respectively.

LLVM Options

The LLVM backend options contains many compiler options for optimizing code, turning features of LLVM on or off. Here is a list of some of the flags for the LLVM Options given the target_options.llvm_options struct.

.enable_tail_calls = false; 
.enable_loop_unrolling = false;
.enable_slp_vectorization = false; 
.enable_loop_vectorization = false; 
.reroll_loop = false; 
.verify_input = false; 
.verify_output = false;
.merge_functions = false;
.disable_inlining = true;
.disable_mem2reg = false;

The -O3, -O2, -O1 optimization levels for LLVM can be changed by setting the code_gen_optimization_level field to 3, 2, 1 respectively. For example, target_options.llvm_options.code_gen_optimization_level = 2 will set the LLVM options to -O2.

Debug Options can be passed directly to LLVM’s cl::ParseCommandLineOptions() function through
the field debug_options.

A more comprehensive set of compiler options and details can be found under Compiler.jai.