pass-lang/src/ir.h

117 lines
3.6 KiB
C

#ifndef _IR_H
#define _IR_H
#include <stddef.h>
#include <stdint.h>
typedef uint32_t var;
typedef uint32_t label;
struct jump_target {
label label;
var* args;
};
/// Declare a new label in the current scope with the provided number
/// of arguments.
///
/// Local variables (not part of a stack frame generated by `define` or `enter`)
/// will not be in scope of the definition of the label.
label declare(uint32_t argc);
/// Define a label and create a new scope for local variables.
///
/// The new scope will have access to all of the variables
/// of the parent scope of the label and the label's arguments,
/// but not any local variables from previous definitions.
void define(label label, var* args);
/// Create a new scope which encompasses all local variables defined up to this point.
///
/// This allows nested definitions to have access to local variables.
void enter(void);
/// Jump to label, unconditionally. Ends the continuation.
void jump(struct jump_target dest);
/// Jump to `then` if `cond` is not zero; jump to `else` otherwise.
/// Ends the continuation.
void jump_if(struct jump_target then, struct jump_target else_, var cond);
/// Jump to the `index`th destination. Ends the continuation.
void jump_table(uint32_t destc, struct jump_target* destinations, var index);
/// 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 `then` if cond is not zero, `else` if cond is zero.
void jump_if(label then, label else_, 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