irbuilder.rst 48.2 KB
Newer Older
1 2 3
======================================
Function Call-based Mu IR Building API
======================================
4

5
This chapter describes the function call-based Mu IR building API. It is part of
6
the `Mu Client Interface <api.rst>`__.
7

8
The C functions and types are also defined in `<muapi.h>`__.
9

10 11 12 13
Purpose and the Principles of Design
====================================

There must be a way for the client to load Mu IR bundles into the micro VM.
14 15

Both text- or binary-encoded IR require parsers, which is difficult to verify.
16 17 18 19
This API, instead, consists of a set of functions rather than well-known data
format.

In this API, the client builds the Mu IR bundle by calling API functions. Each
20 21 22
function creates an AST node inside the micro VM and gives the client the ID of
it. When finished building, the client calls another API function
(``MuIRBuilder.load``) to tell the micro VM to load the bundle.
23 24 25 26

    For LLVM users: Like the LLVM API, the client creates nodes by invoking
    functions. But in Mu, AST nodes are held within the micro VM, and is opaque
    to the client.
27 28 29 30 31
    
    Also unlike LLVM, nodes are immutable, and refer to each other by IDs rather
    than references. This is to support the micro VM implementations in
    functional languages and Rust, where cyclic references and mutable fields
    are forbidden.
32 33

All API functions are also available as `common instructions
34
<common-insts.rst>`__.
35 36

This API is minimal, just like other parts of the Mu Client API. For example,
37 38 39 40 41 42
the AST is immutable, so it is not suitable to be used by the client for
arbitrary transformations. However, clients or middle-wares may provide
higher-level abstractions over this API, such as supporting non-SSA forms, or
supporting other serialisable forms such as the text form. Currently the API
still accepts text-form IR, but in the future we plan to move it outside the
micro VM.
43 44 45 46

Overview
========

47 48
The ``MuCtx`` struct has a ``new_ir_builder`` method which creates a
``MuIRBuilder`` struct::
49

50
    struct MuCtx {
51

52
        // more members here
53

54
        MuIRBuilder*    (*new_ir_builder)(MuCtx *ctx);
55
    };
56

57 58
    struct MuIRBuilder {
        void *header;   // Implementation-specific private field
59

60 61 62 63 64 65
        void (*load         )(MuIRBuilder *b);
        void (*abort        )(MuIRBuilder *b);
        MuID (*gen_sym      )(MuIRBuilder *b, MuCString name);
        void (*new_type_int )(MuIRBuilder *b, MuID id, int len);
        ...
    };
66

67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
Like ``MuVM`` and ``MuCtx``, ``MuIRBuilder`` is also a struct of function
pointer fields. The first parameter of these methods is always the pointer to
the ``MuIRBuilder``. 

IR Nodes
--------

The Mu IR is represented as an AST, similar to the text form.

In this API, AST nodes are represented as their IDs. Their IDs are simply the
``MuID`` type. For readability, the ``muapi.h`` header also define concrete node
types which are aliases of the ``MuID`` type. C is not an object-oriented
language and thus cannot perform real type checking. The actual nodes
acceptable for each typedef is listed in the comments after each line::

    typedef MuID MuTypeNode;        // Type
    typedef MuID MuFuncSigNode;     // Function signature
    typedef MuID MuVarNode;         // Variable: constant, global cell, function, expfunc, parameter, instruction result
    typedef MuID MuGlobalVarNode;   // Global variable: constant, global cell, function, expfunc
    typedef MuID MuLocalVarNode;    // Local variable: parameter, instruction result
    typedef MuID MuConstNode;       // Constant (actually a kind of global var)
    typedef MuID MuFuncNode;        // Function (actually a kind of global var)
    typedef MuID MuFuncVerNode;     // Function version
    typedef MuID MuBBNode;          // Basic block
    typedef MuID MuInstNode;        // Instruction itself, not its results
    typedef MuID MuDestClause;      // Destination clause: branching detination
    typedef MuID MuExcClause;       // Exception clause
    typedef MuID MuKeepaliveClause; // Keep-alive clause
    typedef MuID MuCurStackClause;  // Current stack clause (SWAPSTACK)
    typedef MuID MuNewStackClause;  // New stack clause (NEWTHREAD, SWAPSTACK)
 
IRBuilder Lifetime
------------------
100

101 102
Each ``IRBuilder`` object creates exactly one bundle. The bundle contains all
nodes in the ``IRBuilder``
103

104 105 106 107
During construction, the ``IRBuilder`` object owns the nodes it created.
Multiple ``IRBuilder`` objects may exist at the same time, but each
``IRBuilder`` can only address other nodes it created and the nodes that are
already loaded into the micro VM.
108

109 110 111 112
When the ``load()`` method is called, it loads the bundle into the micro VM.
Then the ``IRBuilder`` is destroyed and all resources it occupied are freed. The
``abort()`` method also destroys the ``IRBuilder`` and releases its resources,
but does not load the bundle, as if the ``IRBuilder`` never existed.
113

114 115
How to Use
----------
116

117 118
The first step is to create an ``IRBuilder`` object by calling the
``new_ir_builder`` method on the ``MuCtx`` object::
119

120
    MuIRBuilder b = ctx->new_ir_builder(ctx);
121

122 123 124
All **IDs** are generated by the ``gen_sym`` function. It takes an optional ``name``
parameter. If not ``NULL``, it will be the Mu name (in the form of the *global
name* syntax, such as ``@hello123.bye456.78_9-10``) associated to that ID::
125

126 127 128 129
    MuID i32     = b->gen_sym(b, "@i32");
    MuID ptr_i32 = b->gen_sym(b, "@ptr_i32");
    MuID main    = b->gen_sym(b, "@main");
    MuID my_exception_clause = b->gen_sym(b, NULL); // The name is optional.
130

131
..
132

133 134 135
    NOTE: Names are always optional. You may construct an entire bundle using
    IDs only, without giving anything a name. But the micro VM implementations
    may provide more debug information if the name is available.
136

137 138 139
Then you define the nodes by mentioning its ID as well as the IDs of other nodes
it depends on. These constructors return void. (In fact, ``gen_sym`` is the only
method that does not return void.)
140

141
::
142

143 144
    b->new_type_int (b, i32, 32);       // .typedef @i32 = int<32>
    b->new_type_uptr(b, ptr_i32, i32);  // .typedef @ptr_i32 = uptr<i32>
145

146 147 148
You **don't** need to construct the nodes in the same order as their
dependencies. This means, once the ID is created by ``gen_sym``, forward
references are allowed everywhere::
149

150 151
    b->new_type_uptr(b, ptr_i32, i32);
    b->new_type_int (b, i32, 32);
152

153 154
This applies to recursive nodes, too. For example, to implement the C struct
``struct List { int v; struct List *next; }``::
155

156 157 158
    MuID list_t  = b->gen_sym(b, NULL);
    MuID int_t   = b->gen_sym(b, NULL);
    MuID plist_t = b->gen_sym(b, NULL);
159

160 161 162 163
    MuID fields[] = {int_t, plist_t};
    b->new_type_struct(b, list_t, fields, 2);
    b->new_type_int   (b, int_t, 32);
    b->new_type_uptr  (b, plist_t, list_t);   // recursion on pointer
164

165 166 167 168
All nodes are identified by IDs, including sub-components of instructions, such
as `destination clauses <instruction-set.rst#destination-clause>`__, `exception
clauses <instruction-set.rst#exception-clause>`__, `keep-alive clauses
<instruction-set.rst#keep-alive-clause>`__ and so on::
169

170 171 172
    MuID exc_clause = b->gen_sym(b, "@my_favourite_exception_clause");
    MuID ka_clause  = b->gen_sym(b, "@my_favourite_keep-alive_clause");
    MuID inst_call  = b->gen_sym(b, "@my_favourite_call_site");
173

174 175
    b->new_exc_clause(b, exc_clause, .....);
    b->new_keepalive_clause(b, ka_clause, ......);
176

177 178 179
    MuID ret_vals[] = {...};
    MuID args[] = {...};
    b->new_call(b, inst_call, ret_vals, ..., args, ..., exc_clause, ka_clause);
180

181 182 183 184 185
    NOTE: The API will not stop you from getting the name by the ID of such
    nodes, such as exception clauses. But the ID will not let you do anything to
    it. Only the IDs of top-level definitions (types, sigs, consts, global
    cells, functions, expfuncs), function versions and OSR-point instructions
    are useful in the API.
186

187
When you finished creating a bundle, call the ``load`` function::
188

189
    b->load(b);     // destroys b
190

191 192
Then the ``IRBuilder`` ``b`` is destroyed. If you want to build another bundle,
you need another ``IRBUilder``. Create it again from ``MuCtx``::
193

194
    IRBuilder *b2 = ctx->new_ir_builder(ctx);
195

196 197
In the new bundle, you can mention existing nodes loaded in the micro VM by
directly using their IDs::
198

199 200
    MuID refi32 = b2->gen_sym(b2, "@refi32");
    b2->new_type_rer(b2, refi32, i32); // i32 is defined previously.
201

202 203
.. _define-a-function:

204 205 206
To *define* a **function**, two nodes need to be created: A function and a
function version::

207 208
    MuID func    = b->gen_sym(b, NULL);
    MuID funcver = b->gen_sym(b, NULL);
209

210
    b->new_func(b, func, signature_of_func);
211

212 213
    MuID basicblocks[] = {...}
    b->new_func_ver(b, funcver, func, basicblocks, num_of_basicblocks);
214

215
If only the function node is defined but not any function versions, it will
Kunshan Wang's avatar
Kunshan Wang committed
216
create an undefined function.
217

218 219 220 221 222 223
Constructing a *function version* node needs a list of **basic blocks**, and
constructing each *basic block* needs a list of **instructions**. This requires
the client to have a **"bird's eye view"** of the CFG. It is usually not a
problem if the CFG is created in the client side and transferred to the micro VM
using such an API, but this interface may not be pleasant if the client
programmer manually creates the CFG in C::
224

225 226 227 228 229 230
    MuID entry = b.gen_sym(b, NULL);
    MuID entry_param1 = b.gen_sym(b, NULL);
    MuID entry_param2 = b.gen_sym(b, NULL);
    MuID entry_inst1  = b.gen_sym(b, NULL);
    MuID entry_inst2  = b.gen_sym(b, NULL);
    MuID entry_inst3  = b.gen_sym(b, NULL);
231

232 233 234 235
    MuID bb1 = b.gen_sym(b, NULL);
    MuID bb1_param1 = b.gen_sym(b, NULL);
    MuID bb1_inst1  = b.gen_sym(b, NULL);
    MuID bb1_inst2  = b.gen_sym(b, NULL);
236

237 238 239 240 241
    MuID bb2 = b.gen_sym(b, NULL);
    MuID bb2_excparam = b.gen_sym(b, NULL);
    MuID bb2_inst1    = b.gen_sym(b, NULL);
    MuID bb2_inst2    = b.gen_sym(b, NULL);
    MuID bb2_inst3    = b.gen_sym(b, NULL);
242

243 244
    MuID bbs[] = {entry, bb1, bb2};
    b->new_func_ver(b, funcver, func, bbs, 3);
245

246 247 248 249 250 251 252
    MuID entry_params[] = {entry_param1, entry_param2};
    MuID entry_insts[]  = {entry_inst1, entry_inst2, entry_inst3};
    b->new_bb(b, entry, entry_params, 2, MU_NO_ID, entry_insts, 3);

    MuID bb1_params[] = {bb1_param1};
    MuID bb1_insts[]  = {bb1_inst1, bb1_inst2};
    b->new_bb(b, bb1, bb1_params, 1, MU_NO_ID, bb1_insts, 2);
253

254 255
    MuID bb2_insts[]  = {bb2_inst1, bb2_inst2, bb2_inst3};
    b->new_bb(b, bb1, NULL, 0, bb2_excparam, bb2_insts, 3);
256

257 258 259 260
    b->new_binop(b, entry_inst1, ...);
    b->new_cmp(b, entry_inst2, ...);
    b->new_branch2(b, entry_inst3, ...);
    ...
261

262
..
263

264 265 266 267 268 269 270 271 272 273 274 275 276
    For LLVM user: This interface may irritate LLVM programmers. We are facing
    some implementation problems with mutable data structures and cyclic
    reference in the Rust programming language and some functional languages. As
    a solution, the API is kept at a higher-level, using symbolic references
    between nodes which are resolved after bundle loading. On the other hand,
    LLVM is built with C++ programmers in mind, and it even has the
    ``llvm:IRBuilder<T>`` object that constructs the IR in a more or less
    straight-line style, and is definitely more pleasant to use. We suggest the
    client should create its own builders which then converts to the Mu's
    SSA-like CFG style.

Note the ``MU_NO_ID`` in ``new_bb``. Each basic block has an optional `exception
parameter <ir.rst#exception-parameter>`__ which receives caught exceptions. The
Kunshan Wang's avatar
Kunshan Wang committed
277
``MU_NO_ID`` macro is just 0, which means "there is no exceptional parameter for
278 279 280 281 282 283 284 285 286 287 288 289
this basic block".

Some parameters are **arrays**. Arrays are represented as the pointer to its
first element, and are always accompanied by another argument which determines
the size of the array. For example, when creating a function signature::

    void (*new_funcsig)(MuIRBuilder *b, MuID id,
                        MuTypeNode *paramtys, MuArraySize nparamtys,
                        MuTypeNode *rettys, MuArraySize nrettys);

The ``paramtys`` parameter is a pointer to an array of IDs of Mu types. Its
length is ``nparamtys``. Similarly, the length of ``rettys`` is ``nrettys``.
290 291

The contents of the arrays are **copied** into the micro VM, so the client may
292 293
free those arrays after calling the API functions. The IR builder and the client
do not share memory cells.
294 295 296 297 298 299 300

API Functions
=============

Common Conventions
------------------

301 302 303 304 305
Like the rest of the Mu Client API, all functions in ``MuIRBuilder`` take a
``MuIRBuilder*`` as the first parameter.

``gen_sym`` is the only function that generates IDs. All other functions return
``void``.
306

307 308
All **array** parameters also have their length passed via another parameter.
For example, ``MuTypeNode* fieldtys`` in ``new_type_struct`` is followed by
309 310 311 312 313 314 315 316 317 318 319 320 321
``MuArraySize nfieldtys`` which is the length of the ``fieldtys`` array.

::

    typedef uintptr_t MuArraySize;
    
If the array pointer argument (such as ``fieldtys``) is a C ``NULL`` pointer, it
means the array is empty. In this case, the micro VM will disregard the length
argument (such as ``nfieldtys``).

There is one exception: ``MuName`` is ``char*``, but it is ``'\0'``-terminated
ASCII string.

322 323 324 325
Some parameters are **optional**. In this case, passing ``NULL`` (if it has
pointer type) or ``MU_NO_ID`` (if it has ``MuID`` type or its aliases) means
the argument is not supplied. Optional parameters will be explicitly documented.

326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342
Flag Types
----------

Many functions (such as ``new_inst_binop``) have enumeration-like arguments
(such as ``MuBinOptr`` and its values ``MU_BINOP_ADD``, ``MU_BINOP_SUB``, etc.).
In `<muapi.h>`__, these types are defined to be integers and these constants are
defined as macros::

    typedef uint32_t MuFlag;

..

    NOTE: In C, the ``enum`` definition will create constants of ``int`` types,
    but implementations may extend the lengths and introduce potential ABI
    compatibility problems. For this reason, we chose to explicitly use a
    predictable int type ``uint32_t``.

343 344
.. _load:

345 346 347 348 349
Basic Functions
---------------

::

350 351
    void        (*load  )(MuIRBuilder *b);
    void        (*abort )(MuIRBuilder *b);
352

353 354
``load`` loads the bundle into the micro VM.  ``abort`` discards the bundle.
Both functions will destroy the ``MuIRBUilder`` and release its resources.
355 356 357

::

358
    MuID (*gen_sym  )(MuIRBuilder *b, MuCString name);
359
    
360 361 362 363
``gen_sym`` creates an ID to be used by an IR node created later. ``name`` is
the name associated to the IR node that has this ID.

``name`` is **optional**. If ``NULL``, the node will have no name.
364 365 366 367 368 369

Creating Type Nodes
-------------------

::

370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399
    void (*new_type_int     )(MuIRBuilder *b, MuID id, int len);
    void (*new_type_float   )(MuIRBuilder *b, MuID id);
    void (*new_type_double  )(MuIRBuilder *b, MuID id);
    void (*new_type_uptr    )(MuIRBuilder *b, MuID id, MuTypeNode ty);
    void (*new_type_ufuncptr)(MuIRBuilder *b, MuID id, MuFuncSigNode sig);

    void (*new_type_struct  )(MuIRBuilder *b, MuID id,
                              MuTypeNode *fieldtys, MuArraySize nfieldtys);
    void (*new_type_hybrid  )(MuIRBuilder *b, MuID id,
                              MuTypeNode *fixedtys, MuArraySize nfixedtys,
                              MuTypeNode varty);
    void (*new_type_array   )(MuIRBuilder *b, MuID id, MuTypeNode elemty, uint64_t len);
    void (*new_type_vector  )(MuIRBuilder *b, MuID id, MuTypeNode elemty, uint64_t len);
    void (*new_type_void    )(MuIRBuilder *b, MuID id);

    void (*new_type_ref     )(MuIRBuilder *b, MuID id, MuTypeNode ty);
    void (*new_type_iref    )(MuIRBuilder *b, MuID id, MuTypeNode ty);
    void (*new_type_weakref )(MuIRBuilder *b, MuID id, MuTypeNode ty);
    void (*new_type_funcref )(MuIRBuilder *b, MuID id, MuFuncSigNode sig);
    void (*new_type_tagref64)(MuIRBuilder *b, MuID id);

    void (*new_type_threadref     )(MuIRBuilder *b, MuID id);
    void (*new_type_stackref      )(MuIRBuilder *b, MuID id);
    void (*new_type_framecursorref)(MuIRBuilder *b, MuID id);
    void (*new_type_irbuilderref  )(MuIRBuilder *b, MuID id);

The ``new_type_T`` functions create a node for the Mu type ``T``. In all cases,
the ``id`` parameter is the ID of the type.

Some functions take extra parameters:
400

401
- ``new_type_int``: ``len`` is the length of the integer.
402

403 404
- ``new_type_*ref/*ptr``: ``ty`` is the type it refers to. ``sig`` is the
  signature of the function it refers to.
405

406 407
- ``new_type_struct``: ``fieldtys`` is the array of field types, and
  ``nfieldtypes`` is its length.
408

409 410
- ``new_type_hybrid``: ``fixedtys`` is the array of types in the fixed part, and
  ``nfixedtypes`` is its length. ``varty`` is the type of the variable part.
411 412 413 414 415 416 417 418 419

- ``new_type_array`` and ``new_type_vector``: ``elemty`` is the type of the
  element, and ``len`` is the length of the array or vector.

Creating Function Signature Nodes
---------------------------------

::

420 421 422 423 424 425
    void (*new_funcsig)(MuIRBuilder *b, MuID id,
                        MuTypeNode *paramtys, MuArraySize nparamtys,
                        MuTypeNode *rettys, MuArraySize nrettys);

``new_funcsig`` creates a function signature node. ``id`` is the ID of the
signature.
426

427
``paramtys`` and ``rettys`` are the arrays of its parameter types and return
428 429 430 431 432
types, and their lengths are ``nparamtys`` and ``nrettys``, respectively.

Creating Constant Nodes
-----------------------

433 434
.. _new-const-extern:

435 436
::

437 438 439 440 441 442 443
    void (*new_const_int    )(MuIRBuilder *b, MuID id, MuTypeNode ty, uint64_t value);
    void (*new_const_int_ex )(MuIRBuilder *b, MuID id, MuTypeNode ty, uint64_t *values, MuArraySize nvalues);
    void (*new_const_float  )(MuIRBuilder *b, MuID id, MuTypeNode ty, float value);
    void (*new_const_double )(MuIRBuilder *b, MuID id, MuTypeNode ty, double value);
    void (*new_const_null   )(MuIRBuilder *b, MuID id, MuTypeNode ty);
    void (*new_const_seq    )(MuIRBuilder *b, MuID id, MuTypeNode ty, MuGlobalVarNode *elems, MuArraySize nelems);
    void (*new_const_extern )(MuIRBuilder *b, MuID id, MuTypeNode ty, MuCString symbol);
444

445 446
These functions create constant nodes. In call functions, ``id`` is the ID of
the constant.
447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462

- ``new_const_int`` and ``new_const_int_ex`` create an integer constant. These
  functions are applicable for ``int``, ``uptr`` and ``ufuncptr`` types. ``ty``
  is the type of the constant.
  
  - ``new_const_int`` is used if the size of the constant is less than or equal
    to 64 bits. ``value`` is the value. If the Mu type has less than 64 bits, it
    will be truncated.

  - ``new_const_int_ex`` is used if the size of the constant is greater than 64
    bits. The value is segmented into 64-bit words from the least significant
    bits. Lower words are stored first in the ``values`` array, whose length is
    ``nvalues``. The value is truncated if the size of the Mu type is not a
    multiple of 64 bits.

- ``new_const_float`` and ``new_const_double`` create constants of the
463 464
  ``float`` type and the ``double`` type, respectively. ``ty`` must be
  ``float`` or ``double``. ``value`` is the value.
465 466

- ``new_const_null`` creates a ``NULL`` constant of general reference types.
467
  ``ty`` is the type and must be a general reference type.
468 469

- ``new_const_seq`` can create constants of ``struct``, ``array`` or
470 471 472
  ``vector`` types. ``ty`` is the type. ``elems`` points to an array of other
  constants which are the fields or elements. ``nelems`` is the length of the
  array, and must match the actual number of fields or elements of the type.
473

474 475 476 477
- ``new_const_extern`` can create constants of ``uptr`` or ``ufuncptr`` types.
  ``ty`` is the type. ``symbol`` is the symbolic name, which can include ASCII
  characters 33-126 but not 34.

Kunshan Wang's avatar
Kunshan Wang committed
478 479
.. _new-func:

480 481 482 483 484
Creating Other Top-level Nodes
------------------------------

::

485 486 487
    void (*new_global_cell)(MuIRBuilder *b, MuID id, MuTypeNode ty);
    void (*new_func       )(MuIRBuilder *b, MuID id, MuFuncSigNode sig);
    void (*new_exp_func   )(MuIRBuilder *b, MuID id, MuFuncNode func, MuCallConv callconv, MuConstNode cookie);
488

489
In all cases, ``id`` is the ID of the top-level definition.
490

491
- ``new_global_cell`` creates a global cell node. ``ty`` is its type.
492

Kunshan Wang's avatar
Kunshan Wang committed
493 494 495 496
- ``new_func`` creates a function node. ``sig`` is its signature. Function
  *versions* are created separately using ``new_func_ver``. It is allowed to
  create functions without function versions, in which case the function is said
  to be undefined.
497 498 499

- ``new_exp_func`` creates an exposed function node. ``func`` is the function to
  expose; ``callconv`` is the calling convention; ``cookie`` is the cookie.
500 501 502 503 504 505 506 507 508 509 510

The calling conventions are defined as::

    typedef MuFlag MuCallConv;
    #define MU_CC_DEFAULT   ((MuCallConv)0x00)

Creating the Control Flow Graph of a Function Version
-----------------------------------------------------

::

511 512 513
    void (*new_func_ver )(MuIRBuilder *b, MuID id,
                          MuFuncNode func,
                          MuBBNode *bbs, MuArraySize nbbs);
514

515
The ``new_func_ver`` function creates a function version. ``id`` is its ID.
516

517 518
``func`` may be created in the current bundle. It may also be created in a
previous bundle already loaded, in which case it will be defined or redefined.
519

520 521
``bbs`` is the array of basic blocks, and ``nbbs`` is the number of basic
blocks.
522 523

:: 
524 525 526 527 528

    void (*new_bb)(MuIRBuilder *b, MuID id,
                   MuID *nor_param_ids, MuTypeNode *nor_param_types, MuArraySize n_nor_params,
                   MuID exc_param_id,
                   MuInstNode *insts, MuArraySize ninsts);
529
    
530 531 532 533 534 535
``new_bb`` creates a basic block. ``id`` is the ID of the basic block.

``nor_param_ids`` is an array of the IDs of the normal parameters.
``nor_param_types`` is an array of types, each is the type of the corresponding
normal parameter. ``n_nor_params`` is the number of normal parameters, and is
the length of the two arrays before it.
536

537 538
``exc_param_id`` is **optional**. When not ``MU_NO_ID``, it is the ID of the
`excepton parameter <ir.rst#exception-parameter>` of the basic block.
539

Kunshan Wang's avatar
Kunshan Wang committed
540
The ``new_bb`` function defines its normal parameters and exceptional parameter
541 542 543 544 545 546 547 548 549 550 551
nodes.  These parameter nodes are not constructed separately, and can be used
directly inside the basic block as local variables.

``insts`` is an array of instructions in the basic block, and ``ninsts`` is its
length.

Creating Common Sub-components of Instructions
----------------------------------------------

All sub-components (clauses) are referred to by IDs, too. The ``id`` parameters
are their IDs.
552 553 554

::

555 556 557
    void (*new_dest_clause)(MuIRBuilder *b, MuID id,
                            MuBBNode dest,
                            MuVarNode *vars, MuArraySize nvars);
558

559 560
``new_dest_clause`` creates a `destination clause
<instruction-set.rst#destination-clause>`__.
561

562 563
``dest`` is a basic block, and ``vars`` is the list of arguments, and ``nvars``
is the number of arguments.
Kunshan Wang's avatar
Kunshan Wang committed
564

565 566
::

567 568
    void (*new_exc_clause)(MuIRBuilder *b, MuID id,
                           MuDestClause nor, MuDestClause exc);
569

570 571
``new_exc_clause`` creates an `exception clause
<instruction-set.rst#exception-clause>`__.
572

573 574
``nor`` and ``exc`` are the normal destination and exceptional destination,
respectively.
575 576


577 578 579 580
::

    void (*new_keepalive_clause)(MuIRBuilder *b, MuID id,
                                 MuLocalVarNode *vars, MuArraySize nvars);
581

582 583
``new_keepalive_clause`` creates a `keep-alive clause
<instruction-set.rst#keep-alive-clause>`__.
584

585 586
``vars`` is an array or local variables to be introspected, and ``nvars`` is the
length of the array.
587

588
::
589

590 591
    void (*new_csc_ret_with)(MuIRBuilder *b, MuID id, MuTypeNode *rettys, MuArraySize nrettys);
    void (*new_csc_kill_old)(MuIRBuilder *b, MuID id);
592

593 594
These two functions create the `current stack clause
<instruction-set.rst#current-stack-clause>`__ used by the SWAPSTACK instruction.
595

596 597 598 599
``new_csc_ret_with`` creates the ``RET_WITH`` case. ``rettys`` is the array of
return types, and ``nrettys`` is the length.

``new_csc_kill_old`` creates the ``KILL_OLD`` case.
600 601 602

::

603 604 605 606 607 608 609
    void (*new_nsc_pass_values)(MuIRBuilder *b, MuID id,
                                MuTypeNode *tys, MuVarNode *vars, MuArraySize ntysvars);
    void (*new_nsc_throw_exc  )(MuIRBuilder *b, MuID id, MuVarNode exc);

These two functions create the `new stack clause
<instruction-set.rst#new-stack-clause>`__ used by both the NEWSTACK and the
SWAPSTACK instructions.
610

611 612 613 614 615 616
``new_nsc_pass_values`` creates the ``PASS_VALUES`` case. ``tys`` is the array
of the types of the values to pass, ``vars`` is the array of values to pass, and
``ntysvars`` is the length of both arrays.

``new_nsc_throw_exc`` creates the ``THROW_EXC`` case. ``exc`` is the exception
to be thrown to the stack.
617 618 619 620

Creating Instructions
---------------------

621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638
These functions create instructions or add parts to instructions. In call
functions, ``id`` is the ID of the instruction itself (can be used to identify
call sites).

**Instruction result** nodes are defined when creating the instructions. They
can be used in subsequent instructions in the basic block as local variables.

Most instructions return one result. The ID of the result will be the
``result_id`` parameter. Some instructions do not return any results, and there
will not be such parameter. Some instructions (such as ``CMPXCHG``) have
multiple results and will have multiple result parameters. Some instructions
(such as ``CALL``, ``TRAP``, ``WATCHPOINT``, ``CCALL``, ``SWAPSTACK`` and
``COMMINST``, all of which (except ``COMMINST`` happen to be OSR points) have a
variable number of results.  Their corresponding constructor functions will have
an array parameter ``result_ids`` together with its length ``n_result_ids``.

The canonical definition of each instruction is in the `Instruction Set
<instruction-set.rst>`__ chapter.
639 640 641

::

642 643 644 645 646 647
    void (*new_binop )(MuIRBuilder *b, MuID id, MuID result_id,
                       MuBinOptr   optr,
                       MuTypeNode  ty,
                       MuVarNode   opnd1,
                       MuVarNode   opnd2,
                       MuExcClause exc_clause);
Kunshan Wang's avatar
Kunshan Wang committed
648

649 650 651 652 653 654 655 656 657 658 659 660 661 662 663
    void (*new_binop_with_status)(MuIRBuilder *b, MuID id, MuID result_id,
                       MuID *status_result_ids, MuArraySize n_status_result_ids,
                       MuBinOpStatus status_flags,
                       MuBinOptr     optr,
                       MuTypeNode    ty,
                       MuVarNode     opnd1,
                       MuVarNode     opnd2,
                       MuExcClause   exc_clause);  /// MUAPIPARSER exc_clause:optional

    typedef MuFlag MuBinOpStatus;
    #define MU_BOS_N    ((MuBinOpStatus)0x01)
    #define MU_BOS_Z    ((MuBinOpStatus)0x02)
    #define MU_BOS_C    ((MuBinOpStatus)0x04)
    #define MU_BOS_V    ((MuBinOpStatus)0x08)

Kunshan Wang's avatar
Kunshan Wang committed
664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683
    typedef MuFlag MuBinOptr;
    #define MU_BINOP_ADD    ((MuBinOptr)0x01)
    #define MU_BINOP_SUB    ((MuBinOptr)0x02)
    #define MU_BINOP_MUL    ((MuBinOptr)0x03)
    #define MU_BINOP_SDIV   ((MuBinOptr)0x04)
    #define MU_BINOP_SREM   ((MuBinOptr)0x05)
    #define MU_BINOP_UDIV   ((MuBinOptr)0x06)
    #define MU_BINOP_UREM   ((MuBinOptr)0x07)
    #define MU_BINOP_SHL    ((MuBinOptr)0x08)
    #define MU_BINOP_LSHR   ((MuBinOptr)0x09)
    #define MU_BINOP_ASHR   ((MuBinOptr)0x0A)
    #define MU_BINOP_AND    ((MuBinOptr)0x0B)
    #define MU_BINOP_OR     ((MuBinOptr)0x0C)
    #define MU_BINOP_XOR    ((MuBinOptr)0x0D)
    #define MU_BINOP_FADD   ((MuBinOptr)0xB0)
    #define MU_BINOP_FSUB   ((MuBinOptr)0xB1)
    #define MU_BINOP_FMUL   ((MuBinOptr)0xB2)
    #define MU_BINOP_FDIV   ((MuBinOptr)0xB3)
    #define MU_BINOP_FREM   ((MuBinOptr)0xB4)

684 685 686 687 688 689 690 691
``new_binop`` and ``new_binop_with_status`` create a binary operation.

``result_id`` is the result of the operation; ``status_result_ids`` is an array,
each element is a desired status flag result, in the order of N, Z, C, and then
V, and ``n_status_result_ids`` is its length.

``status_flags`` is the set of desired status flags. It is the logical OR
(``|``) of the ``MuBinOIpStatus`` constants.
692 693 694

``optr`` is the binary operator. ``ty`` is the operand type. ``opnd1`` and
``opnd2`` are the two operands.
Kunshan Wang's avatar
Kunshan Wang committed
695

696 697
``exc_clause`` is the **optional** exception clause to handle the
division-by-zero and overflow case of division and remainder operations.
Kunshan Wang's avatar
Kunshan Wang committed
698

699 700 701
``new_binop`` is equivalent to ``new_binop_with_status`` with
``status_result_ids == NULL, n_status_result_ids == 0, status_flags == 0``.

Kunshan Wang's avatar
Kunshan Wang committed
702 703
::

704 705 706 707 708
    void (*new_cmp   )(MuIRBuilder *b, MuID id, MuID result_id,
                       MuCmpOptr  optr,
                       MuTypeNode ty,  
                       MuVarNode  opnd1,
                       MuVarNode  opnd2);
Kunshan Wang's avatar
Kunshan Wang committed
709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742

    typedef MuFlag MuCmpOptr;
    #define MU_CMP_EQ       ((MuCmpOptr)0x20)
    #define MU_CMP_NE       ((MuCmpOptr)0x21)
    #define MU_CMP_SGE      ((MuCmpOptr)0x22)
    #define MU_CMP_SGT      ((MuCmpOptr)0x23)
    #define MU_CMP_SLE      ((MuCmpOptr)0x24)
    #define MU_CMP_SLT      ((MuCmpOptr)0x25)
    #define MU_CMP_UGE      ((MuCmpOptr)0x26)
    #define MU_CMP_UGT      ((MuCmpOptr)0x27)
    #define MU_CMP_ULE      ((MuCmpOptr)0x28)
    #define MU_CMP_ULT      ((MuCmpOptr)0x29)
    #define MU_CMP_FFALSE   ((MuCmpOptr)0xC0)
    #define MU_CMP_FTRUE    ((MuCmpOptr)0xC1)
    #define MU_CMP_FUNO     ((MuCmpOptr)0xC2)
    #define MU_CMP_FUEQ     ((MuCmpOptr)0xC3)
    #define MU_CMP_FUNE     ((MuCmpOptr)0xC4)
    #define MU_CMP_FUGT     ((MuCmpOptr)0xC5)
    #define MU_CMP_FUGE     ((MuCmpOptr)0xC6)
    #define MU_CMP_FULT     ((MuCmpOptr)0xC7)
    #define MU_CMP_FULE     ((MuCmpOptr)0xC8)
    #define MU_CMP_FORD     ((MuCmpOptr)0xC9)
    #define MU_CMP_FOEQ     ((MuCmpOptr)0xCA)
    #define MU_CMP_FONE     ((MuCmpOptr)0xCB)
    #define MU_CMP_FOGT     ((MuCmpOptr)0xCC)
    #define MU_CMP_FOGE     ((MuCmpOptr)0xCD)
    #define MU_CMP_FOLT     ((MuCmpOptr)0xCE)
    #define MU_CMP_FOLE     ((MuCmpOptr)0xCF)

``new_cmp`` creates a new comparing operation. ``optr`` is the comparing
operator. ``ty`` is the operand type. ``opnd1`` and ``opnd2`` are two operands.

::

743 744 745 746 747
    void (*new_conv  )(MuIRBuilder *b, MuID id, MuID result_id,
                       MuConvOptr optr,
                       MuTypeNode from_ty,
                       MuTypeNode to_ty,
                       MuVarNode  opnd);
Kunshan Wang's avatar
Kunshan Wang committed
748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768

    typedef MuFlag MuConvOptr;
    #define MU_CONV_TRUNC   ((MuConvOptr)0x30)
    #define MU_CONV_ZEXT    ((MuConvOptr)0x31)
    #define MU_CONV_SEXT    ((MuConvOptr)0x32)
    #define MU_CONV_FPTRUNC ((MuConvOptr)0x33)
    #define MU_CONV_FPEXT   ((MuConvOptr)0x34)
    #define MU_CONV_FPTOUI  ((MuConvOptr)0x35)
    #define MU_CONV_FPTOSI  ((MuConvOptr)0x36)
    #define MU_CONV_UITOFP  ((MuConvOptr)0x37)
    #define MU_CONV_SITOFP  ((MuConvOptr)0x38)
    #define MU_CONV_BITCAST ((MuConvOptr)0x39)
    #define MU_CONV_REFCAST ((MuConvOptr)0x3A)
    #define MU_CONV_PTRCAST ((MuConvOptr)0x3B)

``new_conv`` creates a new conversion operation. ``optr`` is the operator.
``from_ty`` and ``to_ty`` are the source and destination types, respectively.
``opnd`` is the operand.

::

769 770 771 772 773 774
    void (*new_select)(MuIRBuilder *b, MuID id, MuID result_id,
                       MuTypeNode cond_ty,
                       MuTypeNode opnd_ty,
                       MuVarNode  cond,
                       MuVarNode  if_true,
                       MuVarNode  if_false);
775

Kunshan Wang's avatar
Kunshan Wang committed
776 777 778 779 780 781
``new_select`` creates a ``SELECT`` instruction. ``cond_ty`` and ``opnd_ty`` are
the types of the condition ``cond`` and the two results ``if_true`` (if cond is
true) and ``if_false`` (if cond is false), respectively.

::

782 783 784 785 786
    void (*new_branch )(MuIRBuilder *b, MuID id, MuDestClause dest);
    void (*new_branch2)(MuIRBuilder *b, MuID id,
                        MuVarNode    cond,
                        MuDestClause if_true,
                        MuDestClause if_false);
Kunshan Wang's avatar
Kunshan Wang committed
787

788
``new_branch`` creates a ``BRANCH`` instruction. ``dest`` is the destination.
Kunshan Wang's avatar
Kunshan Wang committed
789

790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806
``new_branch2`` creates a ``BRANCH2`` instruction. ``cond`` is the condition,
and ``if_true`` and ``if_false`` are the two destinations for ``cond`` being
true or false.

All destinations are **destination clauses** and need to be created separately.

    Example::
    
        MuID dest_clause = b->gen_sym(b, NULL);
        MuID bb2         = b->gen_sym(b, NULL);
        MuID arg0        = b->gen_sym(b, NULL);
        MuID arg1        = b->gen_sym(b, NULL);
        MuID inst_branch = b->gen_sym(b, NULL);

        MuID args[] = { arg0, arg1 };
        b->new_dest_clause(b, dest_clause, bb2, args, 2);
        b->new_branch(b, inst_branch, dest_clause);
Kunshan Wang's avatar
Kunshan Wang committed
807 808 809

::

810 811 812 813 814 815 816
    void (*new_switch )(MuIRBuilder *b, MuID id,
                        MuTypeNode   opnd_ty,
                        MuVarNode    opnd,
                        MuDestClause default_dest,
                        MuConstNode  *cases,
                        MuDestClause *dests,
                        MuArraySize  ncasesdests);
817

Kunshan Wang's avatar
Kunshan Wang committed
818 819 820
``new_switch`` creates a ``SWITCH`` instruction. ``opnd_ty`` is the type of
``opnd``. ``opnd`` is the variable to compare against cases.

821 822 823 824 825 826
``default_dest`` is the default destination when none of the cases match the
``opnd``.

``cases`` and ``dests`` are two arrays of equal length ``ncasesdests``. Each
pair of corresponding elements is a constant and a destination for the case that
``opnd`` is equal to that constant.
Kunshan Wang's avatar
Kunshan Wang committed
827 828 829

::

830 831 832 833 834 835 836 837 838 839 840
    void (*new_call    )(MuIRBuilder *b, MuID id, MuID *result_ids, MuArraySize n_result_ids,
                         MuFuncSigNode sig,
                         MuVarNode     callee,
                         MuVarNode     *args, MuArraySize nargs,
                         MuExcClause   exc_clause,
                         MuKeepaliveClause keepalive_clause);

    void (*new_tailcall)(MuIRBuilder *b, MuID id,
                         MuFuncSigNode sig,
                         MuVarNode     callee,
                         MuVarNode     *args, MuArraySize nargs);
Kunshan Wang's avatar
Kunshan Wang committed
841 842 843

``new_call`` and ``new_tailcall`` create the ``CALL`` and ``TAILCALL``
instructions, respectively. ``sig`` is the signature of ``callee``. ``callee``
844 845
is a variable that must have the ``funcref<sig>`` type. ``args`` is the array of
arguments, and ``nargs`` is its length.
Kunshan Wang's avatar
Kunshan Wang committed
846 847

The ``CALL`` instruction can have exception clause and keep-alive variables.
848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890
**Both are optional.**

The ``CALL`` instruction returns multiple results. The IDs of the results are
passed in the ``result_ids`` array whose length is ``n_result_ids``. There are
as many results as the return types of ``sig``.

The "normal" case of the exception clause may use the results of the
instruction, but the "exceptional" case may not.

    NOTE: This does have some inconsistency, such as the fact that this
    instruction (when being the terminal instruction by having the exceptional
    clause) does not really continue within the basic block, and the "results"
    are useless if we consider them as local variables of the basic block. An
    alternative design is to use a different kind of "symbols" for such results,
    such as::

        // Not current API.
        MuID result0 = b->gen_sym_for_inst_result(b, 0);
        MuID result1 = b->gen_sym_for_inst_result(b, 1);

        MuID nor = b->gen_sym(b, NULL);
        MuID exc = b->gen_sym(b, NULL);
        MuID exc_clause = b->gen_sym(b, NULL);
        MuID bb2, bb3, local1, local2, ...;

        MuID nor_args[] = { local1, result0, local2, result1 };
        b->new_dest_clause(b, nor, bb2, nor_args, 4);
        b->new_dest_clause(b, exc, bb3, ...);
        b->new_exc_clause(b, exc_clause, nor, exc);

        b->new_call_terminate(..., exc_clause, ...);

    Then the API will contain two different ``new_call`` variants, one for
    ``CALL`` being the terminal instruction and another for the "fall-through"
    case where ``CALL`` does produce results usable in subsequent instructions.
    There are quite a few instructions like this, and it will cause
    combinatorial explosion in the API.

    Another alternative design is to `allow side exits in the middle of basic
    blocks <https://gitlab.anu.edu.au/mu/general-issue-tracker/issues/65>`__. We
    can let ``CALL`` always fall-through and add an explicit ``BRANCH``
    afterwards for the "normal" case. This design will be cleaner, but will
    result in major IR redesign.
Kunshan Wang's avatar
Kunshan Wang committed
891 892 893

::

894
    void (*new_ret  )(MuIRBuilder *b, MuID id, MuVarNode *rvs, MuArraySize nrvs);
Kunshan Wang's avatar
Kunshan Wang committed
895 896 897 898 899 900

``new_ret`` creates a ``RET`` instruction. ``rv`` is an array of return values
and ``nrvs`` is its length.

::

901
    void (*new_throw)(MuIRBuilder *b, MuID id, MuVarNode exc);
902

Kunshan Wang's avatar
Kunshan Wang committed
903 904 905 906
``new_throw`` creates a ``THROW`` instruction. ``exc`` is the exception.

::

907 908
    void (*new_extractvalue  )(MuIRBuilder *b, MuID id, MuID result_id, MuTypeNode strty, int index,         MuVarNode opnd);
    void (*new_insertvalue   )(MuIRBuilder *b, MuID id, MuID result_id, MuTypeNode strty, int index,         MuVarNode opnd, MuVarNode newval);
Kunshan Wang's avatar
Kunshan Wang committed
909 910 911 912 913 914 915 916

``new_extractvalue`` and ``new_insertvalue`` create the ``EXTRACTVALUE`` and
``INSERTVALUE`` instructions, respectively. ``strty`` is the type of the struct
operand ``opnd``. ``index`` is the index of the field. ``newvalue`` is the new
value of that field.

::

917 918
    void (*new_extractelement)(MuIRBuilder *b, MuID id, MuID result_id, MuTypeNode seqty, MuTypeNode indty,  MuVarNode opnd, MuVarNode index);
    void (*new_insertelement )(MuIRBuilder *b, MuID id, MuID result_id, MuTypeNode seqty, MuTypeNode indty,  MuVarNode opnd, MuVarNode index, MuVarNode newval);
Kunshan Wang's avatar
Kunshan Wang committed
919 920 921 922 923 924 925 926 927

``new_extractelement`` and ``new_insertelement`` create the ``EXTRACTELEMENT``
and ``INSERTELEMENT`` instructions, respectively. ``seqty`` is the type of the
operand ``opnd`` and can be either ``array`` or ``vector``. ``indty`` is the
type of ``index``, the index into the sequence. ``newval`` is the new value of
that element.

::

928
    void (*new_shufflevector )(MuIRBuilder *b, MuID id, MuID result_id, MuTypeNode vecty, MuTypeNode maskty, MuVarNode vec1, MuVarNode vec2,  MuVarNode mask);
929

Kunshan Wang's avatar
Kunshan Wang committed
930 931 932 933 934
``new_shufflevector`` creates a ``SHUFFLEVECTOR`` instruction. ``vecty`` is the
type of ``vec1`` and ``vec2``. ``maskty`` is the type of the ``mask``.

::

935 936 937 938 939 940 941 942 943 944 945 946
    void (*new_new           )(MuIRBuilder *b, MuID id, MuID result_id,
                               MuTypeNode allocty,
                               MuExcClause exc_clause);
    void (*new_newhybrid     )(MuIRBuilder *b, MuID id, MuID result_id,
                               MuTypeNode allocty, MuTypeNode lenty, MuVarNode length,
                               MuExcClause exc_clause);
    void (*new_alloca        )(MuIRBuilder *b, MuID id, MuID result_id,
                               MuTypeNode allocty,
                               MuExcClause exc_clause);
    void (*new_allocahybrid  )(MuIRBuilder *b, MuID id, MuID result_id,
                               MuTypeNode allocty, MuTypeNode lenty, MuVarNode length,
                               MuExcClause exc_clause);
947

Kunshan Wang's avatar
Kunshan Wang committed
948 949
These functions create the ``NEW``, ``NEWHYBRID``, ``ALLOCA``, ``ALLOCAHYBRID``
instructions, respectively. ``allocty`` is the type to allocate. ``lenty`` is
950 951
the type of the ``length`` parameter which is the length of the variable part of
the hybrid.
Kunshan Wang's avatar
Kunshan Wang committed
952

953 954
All of the four instructions may have **optinal** exception clauses:
``exc_clause``.
Kunshan Wang's avatar
Kunshan Wang committed
955 956 957

::

958
    void (*new_getiref       )(MuIRBuilder *b, MuID id, MuID result_id, MuTypeNode refty, MuVarNode opnd);
Kunshan Wang's avatar
Kunshan Wang committed
959 960 961 962 963 964

This functions create the ``GETIREF`` instruction. ``refty`` is the referent
type of the object reference ``opnd``, the operand.

::

965 966 967 968
    void (*new_getfieldiref  )(MuIRBuilder *b, MuID id, MuID result_id, MuBool is_ptr, MuTypeNode refty, int index, MuVarNode opnd);
    void (*new_getelemiref   )(MuIRBuilder *b, MuID id, MuID result_id, MuBool is_ptr, MuTypeNode refty, MuTypeNode indty, MuVarNode opnd, MuVarNode index);
    void (*new_shiftiref     )(MuIRBuilder *b, MuID id, MuID result_id, MuBool is_ptr, MuTypeNode refty, MuTypeNode offty, MuVarNode opnd, MuVarNode offset);
    void (*new_getvarpartiref)(MuIRBuilder *b, MuID id, MuID result_id, MuBool is_ptr, MuTypeNode refty, MuVarNode opnd);
969

Kunshan Wang's avatar
Kunshan Wang committed
970 971 972 973 974 975 976 977 978 979
These functions create the ``GETIREF``, ``GETFIELDIREF``, ``GETELEMIREF``,
``SHIFTIREF`` and ``GETVARPARTIREF`` instructions, respectively. ``is_ptr!=0``
indicates ``refty`` is a pointer type. ``refty`` is the *referent type* of
``opnd`` (the ``T`` in ``ref<T>`` or ``uptr<T>``), the operand.

``index`` is the index into the struct. ``indty`` is the type of the index into
sequence types: ``index``. ``offty`` is the type of the ``offset``.

::

980 981 982 983 984 985 986 987 988 989 990 991 992 993 994
    void (*new_load     )(MuIRBuilder *b, MuID id, MuID result_id,
                          MuBool is_ptr, MuMemOrd ord, MuTypeNode refty, MuVarNode loc,
                          MuExcClause exc_clause);
    void (*new_store    )(MuIRBuilder *b, MuID id,
                          MuBool is_ptr, MuMemOrd ord, MuTypeNode refty, MuVarNode loc, MuVarNode newval,
                          MuExcClause exc_clause);
    void (*new_cmpxchg  )(MuIRBuilder *b, MuID id, MuID value_result_id, MuID succ_result_id,
                          MuBool is_ptr, MuBool is_weak, MuMemOrd ord_succ, MuMemOrd ord_fail,
                          MuTypeNode refty, MuVarNode loc, MuVarNode expected, MuVarNode desired,
                          MuExcClause exc_clause);
    void (*new_atomicrmw)(MuIRBuilder *b, MuID id, MuID result_id,
                          MuBool is_ptr, MuMemOrd ord, MuAtomicRMWOptr optr,
                          MuTypeNode refTy, MuVarNode loc, MuVarNode opnd,
                          MuExcClause exc_clause);
    void (*new_fence    )(MuIRBuilder *b, MuID id, MuMemOrd ord);
Kunshan Wang's avatar
Kunshan Wang committed
995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023

    typedef MuFlag MuMemOrd;
    #define MU_ORD_NOT_ATOMIC   ((MuMemOrd)0x00)
    #define MU_ORD_RELAXED      ((MuMemOrd)0x01)
    #define MU_ORD_CONSUME      ((MuMemOrd)0x02)
    #define MU_ORD_ACQUIRE      ((MuMemOrd)0x03)
    #define MU_ORD_RELEASE      ((MuMemOrd)0x04)
    #define MU_ORD_ACQ_REL      ((MuMemOrd)0x05)
    #define MU_ORD_SEQ_CST      ((MuMemOrd)0x06)

    typedef MuFlag MuAtomicRMWOptr;
    #define MU_ARMW_XCHG    ((MuAtomicRMWOptr)0x00)
    #define MU_ARMW_ADD     ((MuAtomicRMWOptr)0x01)
    #define MU_ARMW_SUB     ((MuAtomicRMWOptr)0x02)
    #define MU_ARMW_AND     ((MuAtomicRMWOptr)0x03)
    #define MU_ARMW_NAND    ((MuAtomicRMWOptr)0x04)
    #define MU_ARMW_OR      ((MuAtomicRMWOptr)0x05)
    #define MU_ARMW_XOR     ((MuAtomicRMWOptr)0x06)
    #define MU_ARMW_MAX     ((MuAtomicRMWOptr)0x07)
    #define MU_ARMW_MIN     ((MuAtomicRMWOptr)0x08)
    #define MU_ARMW_UMAX    ((MuAtomicRMWOptr)0x09)
    #define MU_ARMW_UMIN    ((MuAtomicRMWOptr)0x0A)

These functions create the ``LOAD``, ``STORE``, ``CMPXCHG``, ``ATOMICRMW``
and ``FENCE`` instructions, respectively.

``is_ptr!=0`` indicates the ``loc`` is a pointer. ``refty`` is the reference
type of it. ``loc`` is the memory location. ``ord`` is the memory order.

1024 1025 1026 1027
For ``new_load``, ``result_id`` is the result: the value in the memory.

For ``new_store``, ``newval`` is the value to store. ``STORE`` does not produce
any results.
Kunshan Wang's avatar
Kunshan Wang committed
1028 1029 1030

For ``new_cmpxchg``, ``weak!=0`` means the operation is weak.  ``ord_succ`` and
``ord_fail`` are the memory orders of the successful and failed cases,
1031 1032 1033
respectively. ``CMPXCHG`` produces two results. ``value_result_id`` is the ID of
the result that holds the old value in the memory; ``succ_result_id`` is the
result of type ``int<1>`` that indicates whether the operation is successful.
Kunshan Wang's avatar
Kunshan Wang committed
1034 1035

For ``new_atomicrmw``, ``optr`` is the binary operator, ad ``opnd`` is the
1036
right-hand-side. ``result_id`` is the result: the old value in the memory.
Kunshan Wang's avatar
Kunshan Wang committed
1037

1038
The exception clause ``exc_clause`` in all of them are **optional**.
Kunshan Wang's avatar
Kunshan Wang committed
1039 1040

::
1041
    
1042 1043 1044 1045 1046 1047 1048 1049 1050
    void (*new_trap      )(MuIRBuilder *b, MuID id,
                           MuID *result_ids, MuTypeNode *rettys, MuArraySize nretvals,
                           MuExcClause exc_clause, MuKeepaliveClause keepalive_clause);
    void (*new_watchpoint)(MuIRBuilder *b, MuID id, MuWPID wpid,
                           MuID *result_ids, MuTypeNode *rettys, MuArraySize nretvals,
                           MuDestClause dis, MuDestClause ena, MuDestClause exc,
                           MuKeepaliveClause keepalive_clause);
    void (*new_wpbranch  )(MuIRBuilder *b, MuID id, MuWPID wpid,
                           MuDestClause dis, MuDestClause ena);
1051

Kunshan Wang's avatar
Kunshan Wang committed
1052 1053 1054 1055 1056
These functions create the ``TRAP``, ``WATCHPOINT`` and ``WPBRAHCN``
instructions, respectively. ``wpid`` is the watch point ID.

``TRAP`` and ``WATCHPOINT`` are OSR points and therefore can have keep-alive
clauses. ``rettys`` is an array of types of the values the OSR points is
1057 1058 1059 1060
supposed to receive. ``nrettys`` is the length of the array. ``result_ids`` is
the array of the IDs of results. It has the same length as ``nrettys``.

``TRAP`` may have an **optional** exception clause ``exc_clause``.
Kunshan Wang's avatar
Kunshan Wang committed
1061

1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073
For ``WATCHPOINT``,

- ``dis`` is the destination when the watchpoint is disabled;
- ``ena`` is the normal destination when the watchpoint is enabled; and
- ``exc`` is the **optional** exceptional destination when the watchpoint is
  enabled.

Both ``TRAP`` and ``WATCHPOINT`` may have **optional** keep-alive clause
``keepalive_clause``.

``WPBRANCH`` is a binary branch. ``dis`` and ``ena`` are the two destinations
for the case when ``wpid`` is disabled and enabled, respectively.
Kunshan Wang's avatar
Kunshan Wang committed
1074 1075 1076

::

1077 1078 1079 1080 1081 1082 1083 1084
    void (*new_ccall)(MuIRBuilder *b, MuID id, MuID *result_ids, MuArraySize n_result_ids,
                      MuCallConv    callconv,
                      MuTypeNode    callee_ty,
                      MuFuncSigNode sig,
                      MuVarNode     callee,
                      MuVarNode     *args, MuArraySize nargs,
                      MuExcClause   exc_clause,
                      MuKeepaliveClause keepalive_clause);
1085

Kunshan Wang's avatar
Kunshan Wang committed
1086 1087 1088 1089 1090 1091 1092 1093
    typedef MuFlag MuCallConv;
    #define MU_CC_DEFAULT   ((MuCallConv)0x00)

``new_ccall`` creates a ``CCALL`` instruction. ``callconv`` is the calling
convention. ``callee_ty`` is the type of ``callee``, which is usually a
``ufuncptr``. ``sig`` is the signature of the function. ``args`` is the array of
arguments, and its length is ``nargs``.

1094 1095 1096 1097 1098 1099
The exception clause ``exc_clause`` and the keep-alive clause
``keepalive_clause`` are both **optional**.

``CCALL`` produces multiple results determined by the return types of ``sig``.
The IDs of the results are in the array ``result_ids``, and the length is
``n_result_ids``.
Kunshan Wang's avatar
Kunshan Wang committed
1100

1101
::
1102

1103 1104 1105 1106 1107
    void (*new_newthread)(MuIRBuilder *b, MuID id, MuID result_id,
                          MuVarNode        stack,
                          MuVarNode        threadlocal,
                          MuNewStackClause new_stack_clause,
                          MuExcClause      exc_clause);
1108

1109
``new_newthread`` creates a ``NEWTHREAD`` instruction. ``stack`` is the stack to
Kunshan Wang's avatar
Kunshan Wang committed
1110
bind to. ``threadlocal`` is the initial thread-local object reference (see
1111 1112 1113 1114 1115
`Thread and Stack <threads-stacks.rst>`__) and must be a variable of ``ref``
type.  ``threadlocal`` is **optional** and **can be a C NULL pointer**, which
means it is a Mu NULL object reference.

``new_thread`` may have exception clause, which is **optional**.
Kunshan Wang's avatar
Kunshan Wang committed
1116

1117
::
Kunshan Wang's avatar
Kunshan Wang committed
1118

1119 1120 1121 1122 1123 1124
    void (*new_swapstack)(MuIRBuilder *b, MuID id, MuID *result_ids, MuArraySize n_result_ids,
                          MuVarNode         swappee,
                          MuCurStackClause  cur_stack_clause,
                          MuNewStackClause  new_stack_clause,
                          MuExcClause       exc_clause,
                          MuKeepaliveClause keepalive_clause);
Kunshan Wang's avatar
Kunshan Wang committed
1125

1126 1127
``new_swapstack`` creates a ``SWAPSTACK`` instruction. ``swappee`` is the stack
it swaps to.
Kunshan Wang's avatar
Kunshan Wang committed
1128

1129 1130 1131 1132
When the current-stack clause ``cur_stack_clause`` is ``RET_WITH``, it is an OSR
point. In this case, the instruction produces as many results as the types in
the ``cur_stack_clause``. It can have **optional** exception clause and
keep-alive clause, too.
Kunshan Wang's avatar
Kunshan Wang committed
1133

1134 1135 1136
When ``cur_stack_clause`` is ``KILL_OLD``, this instruction does not continue,
nor does it produce any results. It cannot have exception clause or keep-alive
clause.
Kunshan Wang's avatar
Kunshan Wang committed
1137

1138 1139
In both cases, the new-stack clause ``new_stack_clause`` determines how to
resume from the ``swappee`` stack.
Kunshan Wang's avatar
Kunshan Wang committed
1140 1141 1142

::

1143 1144 1145 1146 1147 1148 1149 1150
    void (*new_comminst)(MuIRBuilder *b, MuID id, MuID *result_ids, MuArraySize n_result_ids,
                         MuCommInst opcode,
                         MuFlag        *flags, MuArraySize nflags,
                         MuTypeNode    *tys,   MuArraySize ntys,
                         MuFuncSigNode *sigs,  MuArraySize nsigs,
                         MuVarNode     *args,  MuArraySize nargs,
                         MuExcClause       exc_clause,
                         MuKeepaliveClause keepalive_clause); 
1151

Kunshan Wang's avatar
Kunshan Wang committed
1152 1153 1154 1155 1156
This creates a ``COMMINST`` instruction. ``opcode`` identifies the common
instruction (see the next section). ``flags``, ``tys``, ``sigs`` and ``args``
are the arrays of flags, types, signature and value arguments, and their lengths
are specified by the arguments with ``n``.

1157 1158 1159 1160 1161 1162
The IDs of the results are provided by the ``result_ids`` array, and its length
is ``n_result_ids``.

The exception clause and keep-alive clause are **optional** if the concrete
common instruction allows them, otherwise they must be ``MU_NO_ID``.

Kunshan Wang's avatar
Kunshan Wang committed
1163 1164 1165 1166 1167 1168 1169
Common instruction opcode constants are encoded with ``MU_CI_`` as prefix and
without ``@``. All letters are upper case and all dots ``.`` are replaced with
underscore ``_``.  For example, ``@uvm.new_stack`` becomes
``MU_CI_UVM_NEW_STACK``. This specification makes sure there is not name
conflict under this naming scheme. The complete list of common instruction
opcodes is in the `<muapi.h>`__ header.

1170
.. vim: tw=80