+ PROCEDURE TO CONSTRUCT AN IR GRAPH
+ ==================================
+
+ This library supplies several interfaces to construct a FIRM graph for
+ a program:
+ * A "comfortable" interface generating SSA automatically. Automatically
+ computed predecessors of nodes need not be specified in the constructors.
+ (new_<Node> constructurs and a set of additional routines.)
+ * A less comfortable interface where all predecessors except the block
+ an operation belongs to need to be specified. SSA must be constructed
+ by hand. (new_<Node> constructors and switch_block()). This interface
+ is called "block oriented". It automatically calles the local optimizations
+ for each new node.
+ * An even less comfortable interface where the block needs to be specified
+ explicitly. This is called the "raw" interface. (new_r_<Node>
+ constructors). These nodes are not optimized.
+
+ To use the functionality of the comfortable interface correctly the Front
+ End needs to follow certain protocols. This is explained in the following.
+ To build a correct IR with the other interfaces study the semantics of
+ the firm node (See tech-reprot UKA 1999-44). For the construction of
+ types and entities see the documentation in those modules.
+
+ First the Frontend needs to decide which variables and values used in
+ a procedure can be represented by dataflow edges. These are variables
+ that need not be saved to memory as they cause no side effects visible
+ out of the procedure. In general these are all compiler generated
+ variables and simple local variables of the procedure as integers,
+ reals and pointers. The frontend has to count and number these variables.
+
+ First an ir_graph needs to be constructed with new_ir_graph. The
+ constructor gets the number of local variables. The graph is hold in the
+ global variable irg.
+
+ Now the construction of the procedure can start. Several basic blocks can
+ be constructed in parallel, but the code within each block needs to
+ be constructed (almost) in program order.
+
+ A global variable holds the current basic block. All (non block) nodes
+ generated are added to this block. The current block can be set with
+ switch_block(block). If several blocks are constructed in parallel block
+ switches need to be performed constantly.
+
+ To generate a Block node (with the comfortable interface) it's predecessor
+ control flow nodes need not be known. In case of cyclic control flow these
+ can not be known when the block is constructed. With add_in_edge(block,
+ cfnode) predecessors can be added to the block. If all predecessors are
+ added to the block mature_block(b) needs to be called. Calling mature_block
+ early improves the efficiency of the Phi node construction algorithm.
+ But if several blocks are constructed at once, mature_block must only
+ be called after performing all set_values and set_stores in the block!
+ (See documentation of new_immBlock constructor.)
+
+ The constructors of arithmetic nodes require that their predecessors
+ are mentioned. Sometimes these are available in the Frontend as the
+ predecessors have just been generated by the frontend. If they are local
+ values the predecessors can be obtained from the library with a call to
+ get_value(local_val_nr). (local_val_nr needs to be administered by
+ the Frontend.) A call to get_value triggers the generation of Phi nodes.
+ If an arithmetic operation produces a local value this value needs to be
+ passed to the library by set_value(node, local_val_nr).
+ In straight line code these two operations just remember and return the
+ pointer to nodes producing the value. If the value passes block boundaries
+ Phi nodes can be inserted.
+ Similar routines exist to manage the Memory operands: set_store and
+ get_store.
+
+ Several nodes produce more than one result. An example is the Div node.
+ Such nodes return tuples of values. From these individual values can be
+ extracted by proj nodes.
+
+ The following example illustrates the construction of a simple basic block
+ with two predecessors stored in variables cf_pred1 and cf_pred2, containing
+ the code
+ a = a div a;
+ and finally jumping to an other block. The variable a got the local_val_nr
+ 42 by the frontend.
+
+ ir_node *this_block, *cf_pred1, *cf_pred2, *a_val, *mem, *div, *res, *cf_op;
+
+ this_block = new_immBlock();
+ add_in_edge(this_block, cf_pred1);
+ add_in_edge(this_block, cf_pred2);
+ mature_block(this_block);
+ a_val = get_value(17, mode_I);
+ mem = get_store();
+ div = new_Div(mem, a_val, a_val);
+ mem = new_Proj(div, mode_M, 0); * for the numbers for Proj see docu *
+ res = new_Proj(div, mode_I, 2);
+ set_store(mem);
+ set_value(res, 17);
+ cf_op = new_Jmp();
+
+ For further information look at the documentation of the nodes and
+ constructors and at the paragraph COPING WITH DATA OBJECTS at the
+ end of this documentation.
+
+ The comfortable interface contains the following routines further explained
+ below:
+
+ ir_node *new_immBlock (void);
+ ir_node *new_Start (void);
+ ir_node *new_End (void);
+ ir_node *new_Jmp (void);
+ ir_node *new_Cond (ir_node *c);
+ ir_node *new_Return (ir_node *store, int arity, ir_node **in);
+ ir_node *new_Raise (ir_node *store, ir_node *obj);
+ ir_node *new_Const (ir_mode *mode, tarval *con);
+ ir_node *new_SymConst (type_or_id *value, symconst_kind kind);
+ ir_node *new_simpleSel (ir_node *store, ir_node *objptr, entity *ent);
+ ir_node *new_Sel (ir_node *store, ir_node *objptr, int arity,
+ ir_node **in, entity *ent);
+ ir_node *new_Call (ir_node *store, ir_node *callee, int arity,
+ ir_node **in, type_method *type);
+ ir_node *new_Add (ir_node *op1, ir_node *op2, ir_mode *mode);
+ ir_node *new_Sub (ir_node *op1, ir_node *op2, ir_mode *mode);
+ ir_node *new_Minus (ir_node *op, ir_mode *mode);
+ ir_node *new_Mul (ir_node *op1, ir_node *op2, ir_mode *mode);
+ ir_node *new_Quot (ir_node *memop, ir_node *op1, ir_node *op2);
+ ir_node *new_DivMod (ir_node *memop, ir_node *op1, ir_node *op2);
+ ir_node *new_Div (ir_node *memop, ir_node *op1, ir_node *op2);
+ ir_node *new_Mod (ir_node *memop, ir_node *op1, ir_node *op2);
+ ir_node *new_Abs (ir_node *op, ir_mode *mode);
+ ir_node *new_And (ir_node *op1, ir_node *op2, ir_mode *mode);
+ ir_node *new_Or (ir_node *op1, ir_node *op2, ir_mode *mode);
+ ir_node *new_Eor (ir_node *op1, ir_node *op2, ir_mode *mode);
+ ir_node *new_Not (ir_node *op, ir_mode *mode);
+ ir_node *new_Shl (ir_node *op, ir_node *k, ir_mode *mode);
+ ir_node *new_Shr (ir_node *op, ir_node *k, ir_mode *mode);
+ ir_node *new_Shrs (ir_node *op, ir_node *k, ir_mode *mode);
+ ir_node *new_Rot (ir_node *op, ir_node *k, ir_mode *mode);
+ ir_node *new_Cmp (ir_node *op1, ir_node *op2);
+ ir_node *new_Conv (ir_node *op, ir_mode *mode);
+ ir_node *new_Load (ir_node *store, ir_node *addr);
+ ir_node *new_Store (ir_node *store, ir_node *addr, ir_node *val);
+ ir_node *new_Alloc (ir_node *store, ir_node *size, type *alloc_type,
+ where_alloc where);
+ ir_node *new_Free (ir_node *store, ir_node *ptr, ir_node *size,
+ type *free_type);
+ ir_node *new_Proj (ir_node *arg, ir_mode *mode, long proj);
+
+ void add_in_edge (ir_node *block, ir_node *jmp);
+ void mature_block (ir_node *block);
+ void switch_block (ir_node *target);
+ ir_node *get_value (int pos, ir_mode *mode);
+ void set_value (int pos, ir_node *value);
+ ir_node *get_store (void);
+ void set_store (ir_node *store);
+
+