-
Notifications
You must be signed in to change notification settings - Fork 15
inNative Flags
There are 3 kinds of flags: standard, optimization, and feature flags, each specified in a different integer field in the External API. Most flags can also be specified on the Command Line, but the command line name (listed below the C enumeration name) is always an abbreviated form of the C enumeration.
These are behavioral flags that change the binary, the symbol information, or the level of isolation.
Enables every single check and behavioral quirk that the WebAssembly standard demands, producing a WebAssembly binary that is entirely standards compliant. Equivalent to: CHECK_STACK_OVERFLOW
| CHECK_FLOAT_TRUNC
| CHECK_MEMORY_ACCESS
| CHECK_INDIRECT_CALL
| DISABLE_TAIL_CALL
| CHECK_INT_DIVISION
| WHITELIST
Enables only checks that are necessary to safely isolate a webassembly module, which means tail calls are allowed and certain overflow checks are no longer performed. Ensures a safe sandbox, but won't pass the standard webassembly tests. Equivalent to: CHECK_STACK_OVERFLOW
| CHECK_MEMORY_ACCESS
| CHECK_INDIRECT_CALL
| WHITELIST
Enables the C function whitelist. If the whitelist is not enabled, the WebAssembly module will be able to call any C function that it is linked to, which includes all kernel functions on windows, because it is compiled against kernel32.dll
. Enabling the whitelist without providing a list of functions will effectively prevent the WebAssembly module from calling any external C function. Use the -w
option to add C functions to the whitelist.
By default, the environment will not compile .wat
and .wast
files, only binary .wasm modules. This flag enables compilation of both .wat
and .wast
files, provided the runtime has been compiled with support for that. The command line utility always sets this flag, so there's no command line equivalent.
Some platforms, like windows, always require a stack probe if there is any possibility of skipping the stack guard page. This option ensures that a stack probe is always done, even on Linux, if a large amount of stack space is requested. This is critical for sandboxing, because otherwise the stack overflow can be used to break out of the program memory space.
This forces a trap if any floating point truncation to an integer would overflow or underflow the integer due to precision issues. For example, a 64-bit float can accurate hold 52-bit integers with no precision loss, but if you truncate this 64-bit float into a 32-bit integer, the result could potentially overflow the 32-bit integer.
This inserts memory bounds checks on all load and store operations, which is critical for sandboxing applications, but comes at a significant performance cost. Some of these checks can be simplified for certain platforms - 32-bit linear memories on a 64-bit machine only require a single instruction plus a jump, whereas a 64-bit linear memory on a 64-bit platform requires five instructions and a jump.
This inserts a check that verifies the expected type of the indirect function call matches the actual type of the function that is about to be called. This is required for sandboxing because a function call mismatch can smash the stack, but comes at a small performance cost.
Integer division is not actually guaranteed to throw a trap on most hardware, and is considered undefined behavior by LLVM, which can affect optimizations. The WebAssembly standard requires that division by zero always throws a trap, so this inserts checks for both division by zero and MAX_INT
overflow edge cases.
The WebAssembly standard currently does not allow tail calls to prevent stack overflows from turning into endless loops that lock up a web browser. This option is provided purely for compatibility with the standard.
Attempts to compile the modules in parallel as much as possible. Experimental and doesn't always produce much of a speedup at the moment.
Adds debugging information to the WebAssembly module, which may include producing a .pdb
file in addition to the normal output, depending on platform. Currently, this will only produce meaningful debug output for .wat
and .wast
files, as inNative can't automatically deserialize WebAssembly yet. To manually deserialize a .wasm
file, use the -s
option detailed below.
Specifies that the result should be a dynamic library instead of an executable. Any start function will be ignored, and the resulting DLL
or .so
file will export all symbols that are exported from all the modules being compiled. These symbol names will be mangled, but can be accessed from C if you know the resulting mangled name.
You cannot specify the -r
option if this flag is specified. This does not produce a static library because the dynamic library performs initialization and cleanup of global variables when loaded and unloaded. If you know what you're doing, you can perform this initialization yourself by specifying NOINIT
, detailed below.
Outputs a .llvm
file in the target output directory for each module being compiled that outputs the optimized, final LLVM IR that is compiled to machine code. This can be used to investigate compiler bugs or unexpected behavior.
When testing, due to C++ not being able to dynamically generate calling conventions, it is useful to "homogenize" all functions to always return i64
and transform every single parameter into an i64
parameter. This makes it easier to generate function pointers for the test harness. This may be useful for game scripting APIs in certain contexts, but in most cases is unnecessary and simply adds overhead.
Normally, inNative will create a dynamic library that automatically calls it's initialization function when it is loaded into memory, using the operating system's global initialization handles, and free it's global resources when it is unloaded. However, a game may want more precise control over when a WebAssembly module is actually instantiated or freed, and may want the option of freeing and re-instantiating the module without having to unload it from memory. To prevent the initialization and cleanup functions from being automatically called, use this flag, but be sure you call them from your code correctly.
In following example, IN_Entrypoint
, IN_INIT_FUNCTION
and IN_EXIT_FUNCTION
are all defined in innative/export.h
.
void* assembly = (*exports.LoadAssembly)("your_assembly"); // Load the assembly
if(assembly != NULL)
{
// Load the initialization function (which will call the start function, if there is one)
IN_Entrypoint start = (*exports.LoadFunction)(assembly, 0, IN_INIT_FUNCTION);
// Load the cleanup function
IN_Entrypoint exit = (*exports.LoadFunction)(assembly, 0, IN_EXIT_FUNCTION);
if(start != NULL)
{
(*start)();
// Perform any necessary program logic here before calling the cleanup function
if(exit != NULL)
(*exit)();
}
// Release the assembly after calling the cleanup function
(*exports.FreeAssembly)(assembly);
}
These flags control how much optimization is performed on the LLVM IR before it is compiled to machine code. All the O0
/O1
/O2
/O3
/Os
options are mutually exclusive, but can be paired with the FASTMATH
option, which is separate. Enabling optimization levels above O0
can make debugging unreliable or completely impossible. Some optimizations (like FASTMATH
) will violate a strict interpretation of the WebAssembly standard.
No optimization whatsoever is performed. Ensures an accurate debugging experience and can be used to verify that the LLVM IR being produced is precisely what is expected from the input WebAssembly.
Some minor optimizations are performed, like dead code elimination. Attempts are made to avoid invalidating debugging information.
Most optimizations are performed at this level, and no attempt is made to preserve debugging coherency. Avoids some expensive optimizations and loop vectorization.
Performs every imaginable optimization that can be safely done without compromising the sandbox or the math operations. Tries to pull constants out of loops and vectorize them where possible. Re-orders blocks and instructions with no regard to debug information. Aggressively eliminates any code that cannot be traced from an exported function. Does not do unsafe optimizations on floating point operations.
Optimizes for code size, rather than speed, attempting to minimize the resulting executable size as much as possible.
Enables unsafe floating point optimizations that violate the webassembly standard's precision guarantees. If you don't care about precision, these can make things go very, very fast, but watch out for unintended consequences. This applies fastmath to all floating point operations in the entire module. If you only want some operations to be fast, you should make a separate library and link it into your main executable.
This is always set to the maximum optimization level that does not invalidate the standard. This is the optimization level used by the release-mode testing utility when running through the WebAssembly standard tests.
This simply maps to every single optimization available, no matter how dangerous or standards violating it is.
These flags control what version of the standard is being used for validation purposes. The command line utility always enables the highest feature level available (ENV_FEATURE_ALL
), so none of these flags have command line equivalents.
This flag simply allows mutable globals to be exported, as the original standard did not include this.
Equivalent to specifying every single feature flag, even if they are experimental. In the future, a separate ENV_FEATURE_STABLE
option might be provided, when the runtime actually supports experimental features.