uvm-ir.rest 30.5 KB
Newer Older
Kunshan Wang's avatar
Kunshan Wang committed
1 2 3
============================
Intermediate Representation
============================
Kunshan Wang's avatar
Kunshan Wang committed
4

Kunshan Wang's avatar
Kunshan Wang committed
5 6 7
Mu Intermediate Representation, or (Mu IR), is the language used by Mu to
represent a Mu program. It is the input from the client and can be executed on
Mu.
Kunshan Wang's avatar
Kunshan Wang committed
8

Kunshan Wang's avatar
Kunshan Wang committed
9 10
Mu can execute the program in any way, including interpretation, JIT compiling
or even Ahead-of-time compiling.
Kunshan Wang's avatar
Kunshan Wang committed
11

Kunshan Wang's avatar
Kunshan Wang committed
12 13
Mu IR itself has two defined representations: a text form for human readability
and a binary form for compact encoding. Concrete Mu implementations may
Kunshan Wang's avatar
Kunshan Wang committed
14 15
introduce their own formats as long as they are equivalent, in which case the
interface to use and to load them is implementation-specific.
16

Kunshan Wang's avatar
Kunshan Wang committed
17
This document describes the text form and the aspects not specific to the binary
Kunshan Wang's avatar
Kunshan Wang committed
18
form. For the binary form, see `<uvm-ir-binary.rest>`__.
Kunshan Wang's avatar
Kunshan Wang committed
19 20 21

For the documents of the type system and the instruction set, see:

Kunshan Wang's avatar
Kunshan Wang committed
22 23
- `<type-system.rest>`__
- `<instruction-set.rest>`__
Kunshan Wang's avatar
Kunshan Wang committed
24 25 26 27

Example
=======

Kunshan Wang's avatar
Kunshan Wang committed
28
Here is an example of Mu IR in the text form::
Kunshan Wang's avatar
Kunshan Wang committed
29

Kunshan Wang's avatar
Kunshan Wang committed
30 31 32 33
    .typedef @i64 = int<64>
    .typedef @double = double
    .typedef @void = void
    .typedef @refvoid = ref<@void>
Kunshan Wang's avatar
Kunshan Wang committed
34

Kunshan Wang's avatar
Kunshan Wang committed
35 36
    .const @i64_0 <@i64> = 0
    .const @answer <@i64> = 42
Kunshan Wang's avatar
Kunshan Wang committed
37

Kunshan Wang's avatar
Kunshan Wang committed
38 39 40 41
    .typedef @some_global_data_t = struct <@i64 @double @refvoid>
    .global @some_global_data <@some_global_data_t>

    .typedef @Node = struct<@i64 @NodeRef>
Kunshan Wang's avatar
Kunshan Wang committed
42 43
    .typedef @NodeRef = ref<@Node>

44
    .funcsig @BinaryFunc = (@i64 @i64) -> (@i64)
Kunshan Wang's avatar
Kunshan Wang committed
45

Kunshan Wang's avatar
Kunshan Wang committed
46
    .funcdecl @square_sum <@BinaryFunc>
Kunshan Wang's avatar
Kunshan Wang committed
47

48 49 50
    .funcdef @gcd VERSION %v1 <@BinaryFunc> {
        %entry(<@i64> %a <@i64> %b):
            BRANCH %head(%a %b)
Kunshan Wang's avatar
Kunshan Wang committed
51

52
        %head(<@i64> %a <@i64> %b):
Kunshan Wang's avatar
Kunshan Wang committed
53
            %z = EQ <@i64> %b @i64_0
54
            BRANCH2 %z %exit(%a) %body(%a %b)
Kunshan Wang's avatar
Kunshan Wang committed
55

56
        %body(<@i64> %a <@i64> %b):
Kunshan Wang's avatar
Kunshan Wang committed
57
            %b1 = SREM <@i64> %a %b
58
            BRANCH %head(%b %b1)
Kunshan Wang's avatar
Kunshan Wang committed
59

60
        %exit(<@i64> %a):
61
            RET %a
Kunshan Wang's avatar
Kunshan Wang committed
62 63
    }

64 65
    .expose @gcd_native = @gcd < DEFAULT > @i64_0

66 67 68
Later the client can submit a function that defines a previously undefined
function or a new version of a function that replaces the old version::

69
    .funcdef @square_sum VERSION %v1 <@BinaryFunc> {
Kunshan Wang's avatar
Kunshan Wang committed
70
        // define the function (if not defined)
71 72
    }

73
    .funcdef @gcd VERSION %v2 <@BinaryFunc> {
Kunshan Wang's avatar
Kunshan Wang committed
74
        // or replace an existing version (if already defined)
75 76
    }

Kunshan Wang's avatar
Kunshan Wang committed
77 78 79
Top-level Structure
===================

Kunshan Wang's avatar
Kunshan Wang committed
80
A **bundle** is the unit of code the client sends to Mu. It contains many
81 82
**top-level definitions**. A top-level definition shall be a **type
definition**, **function signature definition**, **constant definition**,
83 84
**global cell definition**, **function definition**,  **function declaration**
or **function exposing definition**.
85 86 87

    NOTE: For Java users, a bundle is the counterpart of a Java class file.

Kunshan Wang's avatar
Kunshan Wang committed
88
Identifiers and Names
89 90
---------------------

Kunshan Wang's avatar
Kunshan Wang committed
91
Many entities in Mu are **identified**. An identified entity has an
Kunshan Wang's avatar
Kunshan Wang committed
92
identifiers (ID) and optionally a name. An identifier (ID) is a 32-bit integer.
Kunshan Wang's avatar
Kunshan Wang committed
93
A name is a string starting with a ``@`` or a ``%`` and followed by many
Kunshan Wang's avatar
Kunshan Wang committed
94 95
characters in the set: ``[0-9a-zA-Z_-.]``. An ID uniquely identifies an
*identified* entity. A name also uniquely identifies an *identified* entity.
Kunshan Wang's avatar
Kunshan Wang committed
96 97 98 99

    NOTE: This specification does not define what is an "entity". An English
    dictionary would define "entity" as "a thing with distinct and independent
    existence".
100

Kunshan Wang's avatar
Kunshan Wang committed
101
In the Mu IR text form, names are exclusively used and IDs are automatically
Kunshan Wang's avatar
Kunshan Wang committed
102 103 104 105
generated. When generating IDs, Mu guarantees that there is a **mapping** from
each name to its corresponding ID, and **no two different names are mapped to
the same ID**. In the binary form, IDs are exclusively generated and names can
be introduced via name-binding.
106

Kunshan Wang's avatar
Kunshan Wang committed
107 108 109 110 111 112
    NOTE: There may be multiple different identified entities for the same
    thing. It is allowed to declare two types with the same concrete type::

        .typedef @i64  = int<64>
        .typedef @long = int<64>

Kunshan Wang's avatar
Kunshan Wang committed
113
    In the Mu IR, if ``@i64`` and ``@long`` are declared this way, they can be
Kunshan Wang's avatar
Kunshan Wang committed
114 115 116 117
    used interchangeably. For example, an ``ADD``  instruction can add an
    ``@i64`` value to a ``@long`` value because both are ``int<64>``.

    NOTE: Just because some kinds of entities are identified does not mean all
Kunshan Wang's avatar
Kunshan Wang committed
118 119 120
    entities of that kind in a concrete Mu implementation must have IDs and
    names. Types are one example. Type definitions in the Mu IR are always
    identified, but some Mu instructions may yield values of types that are not
Kunshan Wang's avatar
Kunshan Wang committed
121 122 123
    defined in the IR. For example, the ``CMPXCHG`` instruction on type *T*
    yields a value of type ``struct<T int<1>>`` where the second field indicates
    whether the ``CMPXCHG`` operation is successful. The struct type may not be
Kunshan Wang's avatar
Kunshan Wang committed
124
    defined in the IR, but the Mu IR program cannot make use of the result
Kunshan Wang's avatar
Kunshan Wang committed
125 126 127 128 129 130 131 132 133 134 135 136 137
    unless it defines a type for the struct type because the ``EXTRACTVALUE``
    instruction takes a type parameter which is the type of the struct value
    parameter. For example::

        .typedef @i1 = int<1>
        .typedef @i64 = int<64>
        .typedef @i64_cmpxchg_result = struct<@i64 @i1>

        %result = CMPXCHG SEQ_CST RELAXED <@i64> %opnd %exp %des
        %oldval = EXTRACTVALUE <@i64_cmpxchg_result 0> %result
        %succ   = EXTRACTVALUE <@i64_cmpxchg_result 1> %result

    Instructions of similar property include ``SHUFFLEVECTOR`` (result has a new
138 139 140
    vector type), ``GETIREF`` (ref to iref), ``LOAD`` (converting ``weakref<T>``
    to ``ref<T>``), ``CMPXCHG`` (result is a struct), ``ATOMICRMW`` (same as
    ``LOAD``).
Kunshan Wang's avatar
Kunshan Wang committed
141

142 143
Names
~~~~~
Kunshan Wang's avatar
Kunshan Wang committed
144

Kunshan Wang's avatar
Kunshan Wang committed
145 146
A **global name** begins with ``@``. All identified entities can use global
names. Top-level definitions and the version name of functions must use global
Kunshan Wang's avatar
Kunshan Wang committed
147 148
names. Global names are valid in a whole Mu instance, not limited to a single
bundle.
Kunshan Wang's avatar
Kunshan Wang committed
149

150 151
    Example::

Kunshan Wang's avatar
Kunshan Wang committed
152 153
        .typedef    @i8 = int<8>
        .typedef    @i32 = int<32>
154
        .typedef    @i64 = int<64>
Kunshan Wang's avatar
Kunshan Wang committed
155 156 157
        .typedef    @ir_i8 = iref<@i8>
        .typedef    @ir_ir_i8 = iref<@ir_i8>

158 159
        .funcsig    @some_fun_sig = () -> ()
        .funcsig    @main_sig = (@i32 @ir_ir_i8) -> (@i32)
Kunshan Wang's avatar
Kunshan Wang committed
160 161 162 163 164 165 166

        .const      @i32_1 <@i32> = 1
        .const      @i64_0 <@i64> = 0

        .global     @errno <@i64>

        .funcdecl @some_fun <@some_fun_sig>
167

168
A **local name** begins with ``%``. Function versions, basic blocks, parameters
169
and instruction results may use local names in the IR.
170 171 172 173 174 175 176 177

    NOTE: Local names can only be used in the IR as a syntax sugar. The API
    must use IDs or global names.

The global names are inferred from their syntactic parents:

- Within a function which has the global name ``@FuncGlobalName``, the function
  version ``%FV`` has global name ``@FuncGlobalName.FV``.
178

179 180 181
- Within a function version which has the global name ``@FuncVerGlobalName``, a
  basic block with local name ``%BB`` has global name ``@FuncVerGlobalName.BB``.

182 183 184
- Within a basic block which has the global name ``@BBGlobalName``, a parameter,
  an instruction or an instruction result with local name ``%LN`` has global
  name ``@BBGlobalName.LN``.
185 186

..
187 188 189

    Example::

Kunshan Wang's avatar
Kunshan Wang committed
190
        .funcsig @fac.sig = (... ...) -> (...)
191 192 193

        .funcdef @fac VERSION %v1 <@fac.sig> {
            %entry(<@i32> %n):
194
                [%first_br] BRANCH %head(%n @I32_1 @I32_1)
195 196 197

            %head(<@i32> %n <@i32> %p <@i32> %i):
                %lt = SLT <@i32> %i %n
198
                [%second_br] BRANCH2 %lt %body(%n %p %i) %exit(%p)
199 200 201 202 203 204 205 206

            %body(<@i32> %n <@i32> %p <@i32> %i):
                %p2 = MUL <@i32> %p %i
                %i2 = ADD <@i32> %i @I32_1
                BRANCH %head(%n %p2 %i2)

            %exit(<@i32> %p):
                RET %p
207
        }
Kunshan Wang's avatar
Kunshan Wang committed
208

209 210 211 212 213 214 215 216
    In the above example, the global names of the function version, the basic
    blocks and their parameters and instructions are:

    - ``%v1`` -> ``@fac.v1``

      - ``%entry`` -> ``@fac.v1.entry``

        - ``%n`` -> ``@fac.v1.entry.n``
217
        - ``%first_br`` -> ``@fac.v1.entry.first_br``
218 219

      - ``%head`` -> ``@fac.v1.head``
Kunshan Wang's avatar
Kunshan Wang committed
220

221 222 223 224
        - ``%n`` -> ``@fac.v1.head.n``
        - ``%p`` -> ``@fac.v1.head.p``
        - ``%i`` -> ``@fac.v1.head.i``
        - ``%lt`` -> ``@fac.v1.head.lt``
225
        - ``%second_br`` -> ``@fac.v1.head.second_br``
Kunshan Wang's avatar
Kunshan Wang committed
226

227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267
      - ``%body`` -> ``@fac.v1.body``

        - ``%n`` -> ``@fac.v1.body.n``
        - ``%p`` -> ``@fac.v1.body.p``
        - ``%i`` -> ``@fac.v1.body.i``
        - ``%p2`` -> ``@fac.v1.body.p2``
        - ``%i2`` -> ``@fac.v1.body.i2``
        - The anonymous ``BRANCH`` instruction: no global name.

      - ``%exit`` -> ``@fac.v1.exit``

        - ``%p`` -> ``@fac.v1.exit.p``
        - The anonymous ``RET`` instruction: no global name.

    Note that the same local name, such as ``%p``, has **different global names
    in different basic blocks**. ``@fac.v1.head.p`` and ``@fac.v1.body.p`` are
    not the same. They even seldom have the same value.

    Function versions, basic blocks, parameters and instructions can use global
    names, too. For example, instead of the previous example, it is legal to
    write::

        .funcdef @fac VERSION @fac.v1 <@fac.sig> {
            @fac.v1.entry(<@i32> @fac.v1.entry.n):
                BRANCH @fac.v1.head(<@i32> @fac.v1.entry.n <@i32> @I32_1 <@i32> @I32_1)

            @fac.v1.head(<@i32> @fac.v1.head.n <@i32> @fac.v1.head.p <@i32> @fac.v1.head.i):
                @fac.v1.head.lt = SLT <@i32> @fac.v1.head.i @fac.v1.head.n

    or even::

        .funcdef @fac VERSION @n1 <@fac.sig> {
            @n2(<@i32> @n3):
                BRANCH @n4(<@i32> @n3 <@i32> @I32_1 <@i32> @I32_1)

            @n4(<@i32> @n5 <@i32> @n6 <@i32> @n7)
                @n8 = SLT <@i32> @n7 @n5

Local names are merely syntax sugar. Everything that has a local name can be
identified by their global names. It is still considered a naming conflict if
two local names have the same global name.
Kunshan Wang's avatar
Kunshan Wang committed
268 269 270

..

271 272 273 274 275
    NOTE: It is useful to have local things globally identifiable, especially
    *function call sites* and *traps*. For example::

        .funcdef @foo VERSION @foo.v1 <...> {
            %entry():
276 277
                (%rv1 %rv2 %rv3) = [%the_call_site] CALL <@T1 @T2 @T3> @some_func (...)
                () = [%the_trap] TRAP <> KEEPALIVE (...)
278 279 280
                ...
        }

281 282 283 284
    The call site can be globally identified by ``@foo.v1.entry.the_call_site``.
    The trap can be identified by ``@foo.v1.entry.my_trap``. The name is
    globally unique and can be used to identify individual traps and call sites
    in *trap handlers* (see `the API <uvm-client-interface.rest>`__).
Kunshan Wang's avatar
Kunshan Wang committed
285

Kunshan Wang's avatar
Kunshan Wang committed
286
Identifiers
287
~~~~~~~~~~~
Kunshan Wang's avatar
Kunshan Wang committed
288

Kunshan Wang's avatar
Kunshan Wang committed
289
All identifiers are global. Every ID must uniquely identify one entity in the
Kunshan Wang's avatar
Kunshan Wang committed
290
whole Mu instance.
291

Kunshan Wang's avatar
Kunshan Wang committed
292 293
0 is an invalid ID. IDs in the range of 1-65535 are reserved by Mu. The Mu
specification only uses 1-32767. 32768-65535 can be used by the Mu
294
implementation for extension purposes.
Kunshan Wang's avatar
Kunshan Wang committed
295

Kunshan Wang's avatar
Kunshan Wang committed
296 297 298
Type Definition
===============

Kunshan Wang's avatar
Kunshan Wang committed
299
Types and the **type constructor** syntax are documented in `<type-system.rest>`__.
Kunshan Wang's avatar
Kunshan Wang committed
300

301
A **type definition** gives a name to a type. It has the following form::
Kunshan Wang's avatar
Kunshan Wang committed
302

303
    .typedef Name = TypeCtor
Kunshan Wang's avatar
Kunshan Wang committed
304

305
where:
Kunshan Wang's avatar
Kunshan Wang committed
306

307 308
* ``Name`` is a global name for the type, and
* ``TypeCtor`` is a type constructor which defines the type.
Kunshan Wang's avatar
Kunshan Wang committed
309

310
..
Kunshan Wang's avatar
Kunshan Wang committed
311

312
    Example: The following type definition defines a simple non-recursive type::
Kunshan Wang's avatar
Kunshan Wang committed
313

314
        .typedef @i64 = int<64>
Kunshan Wang's avatar
Kunshan Wang committed
315

316
    It gives a name ``@i64`` to a 64-bit integer.
Kunshan Wang's avatar
Kunshan Wang committed
317

Kunshan Wang's avatar
Kunshan Wang committed
318 319
..

320
    Example: The following type definition defines a recursive type::
Kunshan Wang's avatar
Kunshan Wang committed
321

Kunshan Wang's avatar
Kunshan Wang committed
322 323
        .typedef @i64 = int<64>
        .typedef @Node = struct<@i64 @NodeRef>
324 325 326 327 328 329
        .typedef @NodeRef = ref<@Node>

    These define a node in a singly-linked list. The second field of the struct
    is an object reference to itself. Note that **the order of top-level
    definitions does not matter**. They can be written in any order.

Kunshan Wang's avatar
Kunshan Wang committed
330 331
..

332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352
    NOTE: There is no way to simply make an alias of another type. ``.typedef
    @Foo = @Bar`` is illegal because ``@Bar`` is not a type constructor. In this
    event, replacing all occurrences of ``@Foo`` with ``@Bar`` in the whole
    program is the desired approach.

Function Signature Definition
=============================

A **function signature definition** gives a name to a **function signature**, or
**signature** when unambiguous. It has the following form::

    .funcsig Name = SigCtor

where:

* ``Name`` is a global name for the signature, and
* ``SigCtor`` is a function signature constructor which defines the function
  signature.

A function signature constructor has the form::

353
    (ParamTys) -> (RetTys)
354

355 356
where both ``ParamTys`` and ``RetTys`` are a list of global names separated by
spaces for the types of parameters and return values, respectively.
357

358 359
    Example: The following signature receives no parameters and return no
    values::
Kunshan Wang's avatar
Kunshan Wang committed
360

361
        .funcsig @empty_func_s = () -> ()
362

Kunshan Wang's avatar
Kunshan Wang committed
363 364
    The following signature receives a 64-bit integer and a double as parameters
    and returns an object reference to a 64-bit integer::
365

Kunshan Wang's avatar
Kunshan Wang committed
366 367 368
        .typedef @double = double
        .typedef @i64 = int<64>
        .typedef @refi64 = ref<@i64>
369
        .funcsig @some_func_s = (@i64 @double) -> (@refi64)
Kunshan Wang's avatar
Kunshan Wang committed
370 371 372 373

Constant Definition
===================

374 375
A **constant definition** has the form::

Kunshan Wang's avatar
Kunshan Wang committed
376
    .const Name <Type> = ConstCtor
377 378 379 380

where:

* ``Name`` is global name for the constant;
Kunshan Wang's avatar
Kunshan Wang committed
381
* ``Type`` is a global name for the type of the constant, and
382 383 384 385
* ``ConstCtor`` is a constant constructor.

A **constant constructor** can be the following:

386
- An **integer constructor** creates an integer constant or a pointer constant.
Kunshan Wang's avatar
Kunshan Wang committed
387
  It is written as an **integer literal**, which is:
Kunshan Wang's avatar
Kunshan Wang committed
388 389 390 391 392 393 394
  
  + an optional sign [+-], followed by
  + an optional prefix: ``0`` or ``0x``, and
  + a sequence of digits [0-9a-fA-F].
    
  A prefix 0 represents an octal number. A prefix 0x represents a hexadecimal
  number. Otherwise it is a decimal number.
395

Kunshan Wang's avatar
Kunshan Wang committed
396 397 398
- A **floating point constructor** creates a floating point number. It is
  written as a **floating point literal**, which can be one of the following
  forms:
399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419

  + It has an optional sign [+-], an integral part, a dot (.), a fraction part,
    an optional exponent part and a suffix.

    * Both the integral part and the fraction part are a sequence of decimal
      digits [0-9].
    * The exponent part is ``e`` followed by an optional sign [+-] followed by a
      sequence of decimal digits [0-9].
    * The suffix is either ``f`` (for ``float``) or ``d`` (for ``double``).
    * Example: ``123.456f``, ``+123.456e789d``, ``-123.456e-789d``

  + It is one of ``nan``, ``+inf`` and ``-inf`` with a suffix ``f`` or ``d``.

    * Example: ``nanf``, ``-infd``

  + It is either ``bitsf(intlit)`` or ``bitsd(intlit)`` where ``intlit`` is an
    integer literal and the ``f`` and ``d`` represents ``float`` and ``double``,
    respectively. In the case, the resulting ``float`` and ``double`` value has
    the same bit-wise representation as the 32-bit or 64-bit integer of
    ``intlit``, respectively.

420
- A **list constructor** creates a struct/array/vector constant. It is:
421

Kunshan Wang's avatar
Kunshan Wang committed
422
  + an opening brace ``{``, followed by
423 424
  + a sequence of global names of other global variables separated by spaces,
    and
Kunshan Wang's avatar
Kunshan Wang committed
425 426
  + a closing brace ``}``.

427 428 429
  The sequence of names must have the same number of names as the number of
  fields/elements as the type requires.

Kunshan Wang's avatar
Kunshan Wang committed
430
  A constant must not be recursive.
431

Kunshan Wang's avatar
Kunshan Wang committed
432
- A **null constructor** create a null value of *general reference types* except
Kunshan Wang's avatar
Kunshan Wang committed
433
  ``weakref`` (defined in `<type-system.rest>`__). It is written as the **null
Kunshan Wang's avatar
Kunshan Wang committed
434
  literal**: ``NULL``. 
435

Kunshan Wang's avatar
Kunshan Wang committed
436
..
437

Kunshan Wang's avatar
Kunshan Wang committed
438
    NOTE: The client must ensure the number (integer or floating point) can be
Kunshan Wang's avatar
Kunshan Wang committed
439 440 441 442
    represented by the type, or it is an error.

..

443
    NOTE: ``weakref`` cannot be the type of an SSA variable, but all constants
Kunshan Wang's avatar
Kunshan Wang committed
444
    are SSA variables. (See `<type-system.rest>`__ and `<instruction-set.rest>`__).
445 446 447

..

Kunshan Wang's avatar
Kunshan Wang committed
448
    NOTE: The only constant of reference types is ``NULL``. The reason why Mu
Kunshan Wang's avatar
Kunshan Wang committed
449
    forbids constant object references is manifold:
Kunshan Wang's avatar
Kunshan Wang committed
450

Kunshan Wang's avatar
Kunshan Wang committed
451
    * To define a constant heap reference, the client must provide a reference
Kunshan Wang's avatar
Kunshan Wang committed
452 453 454 455 456 457 458 459 460 461 462 463
      to a heap object, which itself is recursively a constant heap reference.
      Even if such a reference is created, it renders a heap object immortal (as
      immortal as a global cell), which defeated the purpose of garbage
      collection.

    * When a heap object is moved, the garbage collector must update all
      existing references to the object. This makes the constant reference not
      really "constant". Extra difficulties are introduced when such references
      become immediate values in the machine code.

    The global memory is an alternative to such needs. Either store a global
    data structure in the global memory or allocate it in the heap and assign
Kunshan Wang's avatar
Kunshan Wang committed
464 465
    its reference to a global cell. In fact, the ID or the name of any global
    cell is a constant SSA variable of an internal reference to it. The ID or
Kunshan Wang's avatar
Kunshan Wang committed
466
    the name of a Mu function is a constant SSA variable of a ``funcref``.
467 468 469

..

Kunshan Wang's avatar
Kunshan Wang committed
470
    Example of constant definitions::
471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492

        .typedef @i64 = int<64>
        .typedef @float = float
        .typedef @double = double
        .const @oct1 <@i64> = 0
        .const @oct2 <@i64> = +01234567
        .const @dec1 <@i64> = 1234567890
        .const @hex1 <@i64> = -0x123456789abcdef0
        .const @float1 <@float> = 123.456f
        .const @float2 <@float> = +123.456e789f
        .const @float3 <@float> = -123.456e-789f
        .const @float4 <@float> = nanf
        .const @float5 <@float> = +inff
        .const @float6 <@float> = -inff
        .const @float7 <@float> = bitsf(0x7f800000)   // nan
        .const @double1 <@double> = 123.456d
        .const @double2 <@double> = +123.456e789d
        .const @double3 <@double> = -123.456e-789d
        .const @double4 <@float> = nand
        .const @double5 <@float> = +infd
        .const @double6 <@float> = -infd
        .const @double7 <@float> = bitsd(0x7ff0000000000000)   // nan
Kunshan Wang's avatar
Kunshan Wang committed
493 494 495 496 497 498 499

        .typedef @record_t = struct<@i64 @double>
        .const @record <@record_t> = {@dec1 @double1}

        .typedef @nested_record_t = struct<@i64 @record_t @float>
        .const @nested_record <@nested_record_t> = {@hex1 @record @float2} // nesting

500
        .funcsig @noparamsnoret = () -> ()
Kunshan Wang's avatar
Kunshan Wang committed
501

502
        .typedef @void = void
Kunshan Wang's avatar
Kunshan Wang committed
503 504 505 506 507 508
        .typedef @ref_void = ref<@void>
        .const @null_ref <@ref_void> = NULL

        .typedef @iref_void = iref<@void>
        .const @null_iref <@iref_void> = NULL

Kunshan Wang's avatar
Kunshan Wang committed
509
        .typedef @some_func = funcref<@noparamsnoret>
Kunshan Wang's avatar
Kunshan Wang committed
510 511
        .const @null_func <@some_func> = NULL

Kunshan Wang's avatar
Kunshan Wang committed
512 513
        .typedef @tref = threadref
        .const @null_tr <@tref> = NULL
Kunshan Wang's avatar
Kunshan Wang committed
514

Kunshan Wang's avatar
Kunshan Wang committed
515 516
        .typedef @sref = stackref
        .const @null_sr <@sref> = NULL
517

Kunshan Wang's avatar
Kunshan Wang committed
518
        .typedef @4xfloat = vector <@float 4>
519
        .const @vec1 <@4xfloat> = { @float1 @float2 @float3 @float4 }
Kunshan Wang's avatar
Kunshan Wang committed
520

521 522 523 524
        // global cells and functions are global variables, too, and they are constants
        .global @g1 <@i64>
        .funcdecl @f1 <@noparamsnoret>

525
        .typedef @irefi64 = iref<@i64>
526 527 528 529
        .typedef @record2_t = struct<@irefi64 @some_func>

        .const @record2 <@record2_t> = {@g1 @f1}

Kunshan Wang's avatar
Kunshan Wang committed
530 531
        .typedef @ptri64          = uptr<@i64>
        .typedef @fpnoparamsnoret = ufuncptr<@noparamsnoret>
532 533 534 535 536 537

        // Address should be looked up before generating the bundle.
        .const @ptrconst <@ptri64> = 0x12345678
        .const @fpconst  <@fpnoparamsnoret> = 0x7ff00000000
        .const @nullptr  <@ptri64> = 0

538 539 540 541
        // Array constant. Not recommended to use unless intracting with native function.
        .typedef @i64ary = array<@i64 3>
        .const @constary <@i64ary> = {@oct1 @oct2 @dec1}

542

543 544 545 546
Global Cell Definition
======================

A **global cell definition** defines a **global cell**. A global cell is the
Kunshan Wang's avatar
Kunshan Wang committed
547
memory allocation unit in the *global memory*. See `<uvm-memory.rest>`__ for more
548 549 550 551 552 553 554
information about the global memory.

    NOTE: The global memory is the counterpart of static or global variables in
    C/C++.

A global cell definition has the form::

Kunshan Wang's avatar
Kunshan Wang committed
555
    .global Name <Type>
556 557

* where ``Name`` is a global name for the global cell and
Kunshan Wang's avatar
Kunshan Wang committed
558
* ``Type`` is a global name for the type of the data the global cell
559 560 561 562 563 564
  represents.

..

    Example::

Kunshan Wang's avatar
Kunshan Wang committed
565 566 567 568 569
        .typedef    @i8 = int<8>
        .typedef    @i32 = int<32>
        .const      @i32_0 <@i32> = 0

        .global @my_errno <@i32>
570

Kunshan Wang's avatar
Kunshan Wang committed
571
        .typedef @small_char_array = array<@i8 12>
572
        .global @hello_world_str <@small_char_array>
Kunshan Wang's avatar
Kunshan Wang committed
573 574
        
        // The client can populate the memory in @hello_world_str at loading time
575

576 577
        .funcdef @func VERSION ... <...> {
            %entry():
578
                %a = LOAD <@i32> @my_errno       // @my_errno has type iref<@i32>
579 580
                STORE <@i32> @my_errno @i32_0
                ...
581
        }
Kunshan Wang's avatar
Kunshan Wang committed
582 583 584 585

Function Definition and Declaration
===================================

Kunshan Wang's avatar
Kunshan Wang committed
586 587 588 589
**Functions** are callable in Mu. A function is an identified entity. A function
may have multiple versions. A **version of function** has its control flow graph
which defines how it is executed. A version of function is also an identified
entity.
Kunshan Wang's avatar
Kunshan Wang committed
590

Kunshan Wang's avatar
Kunshan Wang committed
591 592 593
A **function definition** defines a *version of function* and, if the function
has not been declared, implicitly defines the *function*. It has the following
form::
Kunshan Wang's avatar
Kunshan Wang committed
594

595
    .funcdef Name VERSION VerName <Sig> { Body }
Kunshan Wang's avatar
Kunshan Wang committed
596

597
where:
Kunshan Wang's avatar
Kunshan Wang committed
598

599 600
* ``Name`` is a global name for the function
* ``VerName`` is a global name of this particular version of function
Kunshan Wang's avatar
Kunshan Wang committed
601
* ``Sig`` is a global name for the signature of the function
602
* ``Body`` is a sequence of instructions, constants and labels.
Kunshan Wang's avatar
Kunshan Wang committed
603

Kunshan Wang's avatar
Kunshan Wang committed
604
..
Kunshan Wang's avatar
Kunshan Wang committed
605

Kunshan Wang's avatar
Kunshan Wang committed
606 607 608
    NOTE: The version is required for each definition. Although calling a
    function will always call the most recent version, stack introspection and
    on-stack replacement still need to know the concrete version.
Kunshan Wang's avatar
Kunshan Wang committed
609

610
..
Kunshan Wang's avatar
Kunshan Wang committed
611

612
    Example::
Kunshan Wang's avatar
Kunshan Wang committed
613

Kunshan Wang's avatar
Kunshan Wang committed
614 615 616
        .typedef @i64 = int<64>
        .typedef @float = float
        .typedef @double = double
Kunshan Wang's avatar
Kunshan Wang committed
617

618
        .funcsig @ExampleSig = (@float @double) -> (@i64)
Kunshan Wang's avatar
Kunshan Wang committed
619

620
        .funcdef @example VERSION %v1 <@ExampleSig> {
621 622
            ...
        }
Kunshan Wang's avatar
Kunshan Wang committed
623

Kunshan Wang's avatar
Kunshan Wang committed
624
A **function declaration** defines a function with no versions. It has the
625
following form::
Kunshan Wang's avatar
Kunshan Wang committed
626

Kunshan Wang's avatar
Kunshan Wang committed
627
    .funcdecl Name <Sig>
Kunshan Wang's avatar
Kunshan Wang committed
628

629
where:
Kunshan Wang's avatar
Kunshan Wang committed
630

631
* ``Name`` is a global name for the function and
Kunshan Wang's avatar
Kunshan Wang committed
632
* ``Sig`` is a global name for the signature of the function.
Kunshan Wang's avatar
Kunshan Wang committed
633

634 635 636
When executing a function without version, it behaves as if it has a hidden
version defined as::

637 638
    .funcdef Name VERSION NoVersion <Sig> {
        %entry(ParamList):
639
            TRAP <> KEEPALIVE (ParamList)
640 641 642
            TAILCALL <Sig> Name (ParamList)
    }

643
That is, it will trap to the client, using all parameters as the keep-alive
644 645 646 647 648 649 650 651
variables. If the stack is ever rebound passing 0 values, it will try to
tail-call the same function (**Not necessarily the same hidden version!** It may
have been defined by the client in the trap!) using the same arguments. If an
exception is thrown when rebound, the ``TRAP`` will re-throw it to the parent
frame. The ``cur_func`` API will return the ID of the function.  This hidden
version is still not a real version, so the ``cur_func_ver`` API will return 0.
The ``TRAP`` is not a real instruction, either, so the ``cur_inst`` API will
also return 0.  ``dump_keepalives`` will dump the arguments.
652

653
It is an error to have multiple function declarations and/or function
Kunshan Wang's avatar
Kunshan Wang committed
654 655 656
definitions of the same function name in the same bundle.

It is an error to declare a function which is previously declared or defined.
Kunshan Wang's avatar
Kunshan Wang committed
657

Kunshan Wang's avatar
Kunshan Wang committed
658 659
See the *Bundle Loading* section for the semantics of bundle loading and
function redefinition.
Kunshan Wang's avatar
Kunshan Wang committed
660 661 662 663

Function Body
=============

664
A function definition has a **function body**.
Kunshan Wang's avatar
Kunshan Wang committed
665

666 667 668 669 670 671 672 673 674 675 676 677 678 679 680
A function body has many **basic block** enclosed between ``{`` and ``}``. A
basic block has the following form::

    Name (ParamList) ExcParam:
        Inst
        Inst
        ...

where ``ParamList`` is a list of type-name pairs: ``<T1> N1 <T2> N2 <T3> N3
...``, which specifies the normal **parameters** to the basic block.
``ExcParam`` is optional.  When present, it has the form ``[ ExcName ]`` where
``ExcName`` is the name of the **exception parameter**, which is also a
(non-normal) parameter. The exception parameter always has the ``ref<void>``
type. Many instructions follow the colon ``:``.

681 682 683 684 685 686 687 688
    Example::

        %bb1(<@T1> %p1 <@T2> %p2 <@T3> %p3):
            ...

        %bb2() [%exc]:
            ...

689 690 691 692 693 694
The first basic block is the **entry block**. The entry block must have as many
parameters as the function parameters (determined by its signature).  The
execution starts from the entry block, and its parameters receive the arguments
to the function. The entry block must not have the exception parameter.

..
Kunshan Wang's avatar
Kunshan Wang committed
695

696 697
    NOTE: The name of the entry block is conventionally called ``%entry``, but
    is not compulsory.
Kunshan Wang's avatar
Kunshan Wang committed
698

699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721
Other basic blocks are executed when branched to. The normal parameters receive
arguments from the branching sites. The exception parameter receives the
exception caught by the branching site as the argument. If the exception
parameter is omitted but the basic block is supposed to receive an exception,
the exception will be silently ignored. A basic block with an exception
parameter must only be used as the exceptional destination of instructions which
can catch exceptions, which currently include ``CALL``, ``TRAP``, ``WATCHPOINT``
and ``SWAPSTACK``.

    An example of a basic block with an exception parameter::

        %entry():
            ...
            %rv = CALL <...> @foo (...) EXC(%nor_dest(%rv) %exc_dest(%a %b %c))

        %nor_dest(<@T0> %p0):
            // process the return value
            // %p0 = %rv

        %exc_dest(<@T1> %p1 <@T2> %p2 <@T3> %p3) [%exc]:
            // handle exceptions here
            // %p1 = %a, %p2 = %b, %p3 = c, %exc = the exception

722 723
Each basic block contains a sequence of **instructions**. An instruction has one
of the following forms::
Kunshan Wang's avatar
Kunshan Wang committed
724

725
    ( Name1 Name2 Name3 ... ) = InstName InstBody
Kunshan Wang's avatar
Kunshan Wang committed
726

727
    Name = InstName InstBody
Kunshan Wang's avatar
Kunshan Wang committed
728

729
    InstName InstBody
Kunshan Wang's avatar
Kunshan Wang committed
730

731 732
The left hand side can be a list of names: ``( Name1 Name2 Name3 ... )``, each
is bound to a result of an instruction.
Kunshan Wang's avatar
Kunshan Wang committed
733

734 735 736
The latter two forms are syntax sugars. A single name without brackets is a
syntax sugar of ``( Name )``. If both the name and the equal sign ``=`` are
omitted, it is equivalent to an empty list of names: ``()``.
Kunshan Wang's avatar
Kunshan Wang committed
737

738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767
The number of results written in the IR must match the actual number of results
the instruction produces.

The ``InstName`` is optional. When present, it has the form ``[ Name ]``, where
``Name`` is the name of the instruction. This can be used to identify a
particular instruction, especially ``CALL`` and ``TRAP``. If ``InstName`` is
absent, the instruction does not have a name.

    Examples:

    ``%call_site`` is the name of the instruction; ``%rv1``, ``%rv2`` and
    ``%rv3`` are the names of return values::

        (%rv1 %rv2 %rv3) = [%call_site] CALL <@sig> @callee (%a1 %a2)

    The instruction has no name; ``%rv`` is the return value::

        %rv = ADD <@i64> %x %y

    ``%trap1`` is the name of the instruction; There is no return values. The
    empty angular bracket ``<>`` means the TRAP is not expecting any return
    values::

        [%trap1] TRAP <> KEEPALIVE (%x %y %z)


The grammar of the ``InstBody`` part for each instruction is defined separately
in `<instruction-set.rest>`__.

    Full example::
Kunshan Wang's avatar
Kunshan Wang committed
768

Kunshan Wang's avatar
Kunshan Wang committed
769
        .typedef @i64 = int<64>
770
        .funcsig @gcd_sig = (@i64 @i64) -> (@i64)
Kunshan Wang's avatar
Kunshan Wang committed
771 772 773

        .const @i64_0 <@i64> = 0

774 775 776
        .funcdef @gcd VERSION %v1 <@gcd_sig> {
            %entry(<@i64> %a <@i64> %b):
                BRANCH %head(%a %b)
Kunshan Wang's avatar
Kunshan Wang committed
777

778
            %head(<@i64> %a <@i64> %b):
Kunshan Wang's avatar
Kunshan Wang committed
779
                %z = EQ <@i64> %b @i64_0
780
                BRANCH2 %z %exit(%a) %body(%a %b)
Kunshan Wang's avatar
Kunshan Wang committed
781

782
            %body(<@i64> %a <@i64> %b):
Kunshan Wang's avatar
Kunshan Wang committed
783
                %b1 = SREM <@i64> %a %b
784
                BRANCH %head(%b %b1)
Kunshan Wang's avatar
Kunshan Wang committed
785

786
            %exit(<@i64> %a):
787
                RET %a
788
        }
Kunshan Wang's avatar
Kunshan Wang committed
789

790
The last instruction of any basic block must be a **terminator instruction**,
791
which is one of the following:
Kunshan Wang's avatar
Kunshan Wang committed
792

793
- ``BRANCH``, ``BRANCH2``, ``SWITCH``, ``WPBRANCH``
794 795 796 797 798 799 800 801
- ``TAILCALL``
- ``RET``
- ``THROW``
- ``SWAPSTACK`` if the "current stack clause" is ``KILL_OLD``
- Some `Common Instructions <common-insts.rest>`__ are always terminators:

  - ``@uvm.thread_exit``

802 803
- Any instructions that may have an **exception clause** and actually have the
  exception clause, which are:
Kunshan Wang's avatar
Kunshan Wang committed
804

805
  - Binary operations (only ``UDIV``, ``SDIV``, ``UREM`` and ``SREM``)
806
  - ``CALL``, ``CCALL``
807 808 809
  - ``NEW``, ``NEWHYBRID``, ``ALLOCA``, ``ALLOCAHYBRID``
  - ``LOAD``, ``STORE``, ``CMPXCHG``, ``ATOMICRMW``
  - ``TRAP``, ``WATCHPOINT``
810
  - ``NEWTHREAD``, ``SWAPSTACK``
811
  - Some `Common Instructions <common-insts.rest>`__ when having exception
812 813 814
    clause

    - ``@uvm.new_stack``
Kunshan Wang's avatar
Kunshan Wang committed
815

816
..
Kunshan Wang's avatar
Kunshan Wang committed
817

818 819 820
    NOTE: This is to say, for example, if a particular ``CALL`` instruction does
    have an exception clause, then it is a terminator. If it does not have
    exceptional clause clause, it is not a terminator.
Kunshan Wang's avatar
Kunshan Wang committed
821

822 823 824
Function Exposing Definition
============================

825
A **function exposing definition** has the following syntax::
826

827
    .expose Name = FuncName CallConv Cookie
828 829 830

where:

831
* ``Name`` is a global name of the exposed function.
832
* ``FuncName`` is the name of a Mu function.
833
* ``CallConv`` is a flag that denotes the calling convention. See platform-specific ABI.
834 835
* ``Cookie`` is the cookie. Must be the global name to a ``int<64>`` constant.

836 837 838
This definition exposes a Mu function *FuncName* as an exposed value, identified
by *Name*, using the calling convention *CallConv*. The *Cookie* is attached to
this exposed value.
839

840
How such an exposed function can be called is implementation-specific.
841

842 843 844 845
    Example::

        .expose @name = @func #DEFAULT @cookie

Kunshan Wang's avatar
Kunshan Wang committed
846 847 848 849
Bundle Loading
==============

The API provides a ``load_bundle`` function. See `the API
Kunshan Wang's avatar
Kunshan Wang committed
850
<uvm-client-interface.rest>`__. This function can be called by multiple client
Kunshan Wang's avatar
Kunshan Wang committed
851 852 853 854 855 856 857 858 859 860 861 862 863 864
threads on their client contexts, and the result is always equivalent to as if
they were loaded in a specific sequence.

In a bundle, if any identified entity has the same ID or name as any existing
identified entities defined in previous bundles, it is an error.

In a function definition, if the function ID or name is the same as an existing
function (which can be created either explicitly by a ``.funcdecl`` or
implicitly by a ``.funcdef``), it must also have the same function signature,
otherwise it is an error. The new function definition **redefines** the
function.

After a function definition redefines a function, all calls to the function that
happen after the bundle loading operation will call the newly defined version of
865
the function. Defines of functions (bundle loading) and uses of functions
866 867 868 869
(including function calls and the creation of stacks, i.e. the
``@uvm.new_stack`` instruction or the ``new_stack`` API) obey the memory model
of the ``RELAXED`` order as if the definition is a store and the use is a load.
See `Memory Model <memory-model.rest>`__.
Kunshan Wang's avatar
Kunshan Wang committed
870 871 872 873

All existing activations of any functions remain unchanged, that is, they remain
to be the old versions of the functions. 

874 875 876 877
    NOTE: Specifically, existing traps (including watchpoints) in older versions
    of functions remain valid. During OSR, redefining a function will not affect
    any existing function activations unless they are explicitly popped by the
    client.
Kunshan Wang's avatar
Kunshan Wang committed
878

Kunshan Wang's avatar
Kunshan Wang committed
879
.. vim: textwidth=80