#ifndef _IR_H #define _IR_H #include #include typedef uint32_t var; typedef uint32_t label; /// Call this at the beginning of execution. /// It performs initialization and stuff. void init_ir(var* argc, var* argv, var* env); /// Enter a new block. /// /// All labels defined in this block will have access to all variables /// which are in scope as of calling `enter`. You will be able to jump /// to any label which is defined in this block from here /// to the symmetric `leave`. /// /// This also generates a new label corresponding with the end of the block, /// which will be automatically defined when you call `leave`. void enter(void); /// Leave a block. /// /// This will restore the context to how it was when `enter` was called, /// plus the return values declared by the call to `declare_continue`. void leave(var* rets); /// Declare a new label in the innermost block. /// /// This label can only be called from the block or nested blocks. /// This label must be called with the given number of arguments. label declare(uint32_t argc); //// Declare an exit label for the surrounding block. /// /// Calling this label will exit the surrounding blocks. /// The usual restrictions for labels apply. label declare_exit(uint32_t retc); // Define a label in the innermost block, automatically terminating /// any previous labels. /// /// All variables defined prior to the beginning of this block will be in scope. /// The arguments associated with the label will be in scope. /// Variables defined *after* the beginning of the block but *prior* to this label /// will *not* be in scope. /// /// From this label you can jump to any label in the enclosing block /// or any parent block. void define(label label, var* args); /// Jump to label, unconditionally; never returns. void jump(label label, var* args); /// Jump to `index`th label in table; never returns. /// /// All labels must be at the same depth and accept the same arguments. /// `index` must not be out of bounds. void jump_table(size_t branches, label* labels, var index, var* args); /// Jump to label if `cond` is not zero. void jump_if(label label, var cond, var* args); /// Jump to label if `cond` is zero. void jump_unless(label label, var cond, var* args); /// Integer literal. var lit(uint64_t lit); /// String literal. var lit_string(char* str); /// Addition. var add(var addend1, var addend2); /// Subtraction. var sub(var subtrahend, var minuend); /// Perform a system call. var syscall(size_t argc, var* args); #endif