Index: native_client_sdk/src/doc/reference/pnacl-bitcode-manual.rst |
diff --git a/native_client_sdk/src/doc/reference/pnacl-bitcode-manual.rst b/native_client_sdk/src/doc/reference/pnacl-bitcode-manual.rst |
new file mode 100644 |
index 0000000000000000000000000000000000000000..dba258082834b409e07a9b73d8f1f21b004a8c24 |
--- /dev/null |
+++ b/native_client_sdk/src/doc/reference/pnacl-bitcode-manual.rst |
@@ -0,0 +1,4740 @@ |
+=================================== |
+PNaCl Bitcode File Reference Manual |
+=================================== |
+ |
+.. contents:: |
+ :local: |
+ :backlinks: none |
+ :depth: 3 |
+ |
+ |
+Introduction |
+============ |
+ |
+This document is a reference manual for the contents of PNaCl bitcode files. It |
+is presented using assembly language *PNaClAsm*. PNaClAsm uses a *static single |
jvoung (off chromium)
2014/06/06 20:09:14
Perhaps mention that there are three layers up fro
Karl
2014/06/30 22:09:06
Good suggestion. Done.
|
+assignment* (SSA) based representation that requires generated results to have a |
+single (assignment) source. PNaClAsm is the textual version of the bitcode file. |
+ |
+PNaClAsm focuses on the semantic content of the file, not the bit-encoding of |
+that content. However, it does provide annotations that allow one to specify how |
+the PNaCl bitcode writer converts the semantic content of a PNaClAsm program, |
+into a specific bit sequence. |
+ |
+Below PNaClAsm is the high-level form of the data stored in PNaCl bitcode |
jvoung (off chromium)
2014/06/06 20:09:15
"Below PNaClAsm is the high-level..."
Sounds a bi
Karl
2014/06/30 22:09:03
Decided to just call it the "textual" form.
|
+files. Each construct in PNaClAsm defines a corresponding *PNaCl record* [ref]. |
+A PNaCl bitcode file is simply a sequence of PNaCl records. The goal of PNaClAsm |
+is to make records easier to read, and not to define a high-level user |
+programming language. |
+ |
+PNaCl records are an abstract encoding of structured data, similar to XML. Like |
+XML, PNaCl records have a notion of tags (i.e. the first element in a record, |
+called a *code*), and nested structures. The nested structures are defined by |
+corresponding *enter* and *exit* block records. |
+ |
+These block records must be used like balanced parentheses to define the block |
+structure that is imposed on top of records. Each exit record must be preceded |
+by a corresponding enter record. Blocks can be nested by nesting enter/exit |
+records appropriately. |
+ |
+The *PNaCl bitcode writer* takes the sequence of records, defined by a PNaClAsm |
+program, and converts each record into a (variable) sequence of bits. The output |
+of each bit sequence is appended together. The resulting generated sequence of |
+bits is the contents of the PNaCl bitcode file. |
+ |
+For every kind of record, there is a default method for converting records into |
+bit sequences. These methods correspond to a notion of *abbreviations* |
+[ref]. Each abbreviation defines a specific bit sequence conversion to be |
+applied. The default conversion methods are simply predefined abbreviations. |
+ |
+The default abbreviations can be overridden with user-specified abbreviations. |
+All user-specified abbreviations are included in the generated bitcode |
+file. Each abbreviation defines how a record is converted to a bit sequences. The |
Jim Stichnoth
2014/06/06 18:24:46
80-col
either "to bit sequences" or "to a bit sequ
|
+*PNaCl bitcode writer* uses these abbreviations to convert the corresponding |
+record sequence into a corresponding bit sequence. As a result, all records have |
+an abbreviation (user or default) associated with them. |
+ |
+The *PNaCl bitcode reader* then uses these abbreviations to convert the bit |
+sequences back into the corresponding records. |
+ |
+Conceptually, abbreviations are used to define how to pack the contents of |
+records into bit sequences. The main reason for defining abbreviations is to |
+save space. The default abbreviations are simplistic and are intended to handle |
+all possible records. The default abbreviations do not really worry about being |
+efficient, in terms of the number of bits generated. |
+ |
+By separating the concepts of PNaCl records and abbreviations, the notion of |
+data compression is cleanly separated from semantic content. This allows |
+different use cases to decide how much effort should be spent on compressing |
+records. |
+ |
+For a JIT compiler that produces bitcode, little (if any) compression should be |
+applied. In fact, the API to the JIT may just be the records themselves. The |
+goal of a JIT is to perform the final translation to machine code as quickly as |
+possible. On the other hand, when delivering across the web, one may want to |
+compress the sequence of bits considerably, to reduce costs in delivering web |
+pages. |
+ |
+Data Model |
+========== |
+ |
+The data model for PNaCl bitcode is fixed at little-endian ILP32: pointers are |
+32 bits in size. 64-bit integer types are also supported natively via the i64 |
+type (for example, a front-end can generate these from the C/C++ type *long |
+long*). |
+ |
+Integers are assumed to be modeled using two's complement. Floating point |
+support is fixed at IEEE 754 32-bit and 64-bit values (f32 and f64, |
jvoung (off chromium)
2014/06/06 20:09:13
I think it's called "double" and "float" in the as
Karl
2014/06/30 22:09:06
Done.
|
+respectively). |
+ |
+ |
+Identifiers |
+=========== |
jvoung (off chromium)
2014/06/06 20:09:14
Feels a bit early to talk about identifiers. Shoul
Karl
2014/06/30 22:09:04
Good point. Moving after PNaCl blocks.
|
+ |
+A program is defined as a sequence of top-level *blocks*. Blocks can be nested |
+within other blocks. Each block defines a sequence of records. |
+ |
+Most of the records, within a block, also define unique values. Each unique |
+value is given a corresponding unique identifier (i.e. *ID*). In PNaClAsm. each |
+kind of block defines its own kind of identifiers. The names of these |
+identifiers are defined by concatenating a prefix character ('@' or '%'), the |
+kind of block (a single character), and a suffix index. The suffix index is |
+defined by the positional location of the defined value within the records of |
+the corresponding block. The indices are all zero based, meaning that the first |
+defined value (within a block) is defined using index 0. |
+ |
+Identifiers are categorized into two types, *local* and *global*. Local |
+identifiers are identifiers that are associated with the implementation of a |
+single function. In that sense, they are local to the block they appear in. |
+ |
+All other identifiers are global. This split is intentional. Global identifiers |
+are used by multiple functions, and therefore must be known in all function |
+implementations. Local identifiers only apply to a single function, and can be |
+reused between functions. The *PNaCl translator* uses this separation to |
+parallelize the compilation of functions. |
+ |
+In general, global identifiers are tied to a specific type of block. Local identifiers |
Jim Stichnoth
2014/06/06 18:24:50
80-col
|
+are unique to the function block they appear in. |
+ |
+Local abbreviation identifiers are unique to the block they appear in. Global |
+abbreviation identifiers are only unique to the block type they are defined |
+for. Different block types can reuse global abbreviation identifiers. |
+ |
+Global identifiers use the prefix character *'@'* while local identifiers use |
+the prefix character *'%'*. |
+ |
+Note that by using positional location to define identifiers (within a block), |
+the values defined in PNaCl bitcode files need not be explicitly included in the |
+bitcode file. Rather, they are inferred by the (ordered) position of the record |
+in the block. This is also intentional. It is used to reduce the amount of data |
+that must be (explicitly) passed to the PNaCl translator, and downloaded though |
+the internet. |
+ |
+In general, most of the records within blocks are assumed to be topologically |
+sorted, putting value definitions before their uses. This implies that records |
+do not need to encode data if they can deduce the corresponding information from |
+their uses. |
+ |
+The most common use of this is that many instructions use the type of their |
+operands to determine the type of the instruction. Again, this is |
+intentional. It allows less information to be stored. |
+ |
+However, for function blocks (which define instructions), no topological sort |
+exists. Loop carried value dependencies simply do not allow topologically |
+sorting. To deal with this, function blocks have a notion of a forward |
+(instruction value) declaration. These declarations must appear before any of |
+the uses of that value, if the (instruction) value is defined later in the |
+function than its first use [ref - Forward type declarations]. |
+ |
+The kinds of identifiers used in PNaClAsm are: |
+ |
+@a |
+ Global abbreviation identifier. |
+ |
+%a |
+ Block local abbreviation identifier. |
+ |
+%b |
+ Function local basic block identifier. |
+ |
+%c |
+ Function local constant identifier. |
+ |
+@f |
+ Global function address identifier. |
+ |
+@g |
+ Global variable/constant address identifier. |
+ |
+%p |
+ Function local parameter identifier. |
+ |
+@t |
+ Global type identifier. |
+ |
+%v |
+ Function local instruction generated value identifier. |
+ |
+PNaCl Blocks |
+============ |
+ |
+Blocks are used to organize records in the bitcode file. The kinds of blocks |
+defined in PNaClAsm are: |
+ |
+Module block |
+ A top-level block defining the program. This block defines global information |
+ used by the program, followed by function blocks defining the implementation |
+ of functions within the program. |
+ |
+Types block |
+ Defines the set of types used by the program. All types used in the program |
+ must be defined in this block. These types consist of primitive types as well |
+ as high level constructs such as vectors and function signatures. |
+ |
+Globals block |
+ Defines the set of global addresses of global variables and constants used by |
+ the program. It also defines how each global (associated with the global |
+ address) is initialized. |
+ |
+Valuesymtab block |
+ Defines textual names for global and function addresses. |
+ |
+Function block |
+ Each function (implemented) in a program has its own block that defines the |
+ implementation of the corresponding function. |
+ |
+Constants block |
+ Each implemented function, that uses constants in its instructions, defines a |
+ constant block. Constants blocks appear within the corresponding function |
+ block. |
+ |
+Abbreviations block |
+ Defines global abbreviations that are used to compress PNaCl records. This |
+ block is segmented into multiple sections, one section for each kind of |
+ block. This block appears at the beginning of the module block. |
+ |
+This section is only intented as a high-level discussion of blocks. Later |
Jim Stichnoth
2014/06/06 18:24:49
intended
Karl
2014/06/30 22:09:05
Done.
|
+subsections will dive more deeply into the constraints on how blocks must be |
+layed out. This section only presents the overall concepts of what types of data |
Jim Stichnoth
2014/06/06 18:24:49
laid
|
+is stored in each of the modules. |
Jim Stichnoth
2014/06/06 18:24:46
are stored
|
+ |
+A PNaCl program consists of a header record and a module block. The header |
+defines a sequence of bytes uniquely identifying the file as a bitcode file. The |
+module block defines the program to run. |
+ |
+Each block, within a bitcode file, defines values. These values are associated |
jvoung (off chromium)
2014/06/06 20:09:13
regarding the earlier comment about swapping the o
|
+with IDs. Each type of block defines different kinds of IDs. The module, types, |
+globals, and abbreviations blocks define global identifiers, and only a single |
+instance can appear. The function and constant blocks define local identifiers, |
+and can have mlutiple instances (one for each implemented function). |
Jim Stichnoth
2014/06/06 18:24:48
multiple
jvoung (off chromium)
2014/06/06 20:09:15
multiple
|
+ |
+Each *function block* [ref] defines the implementation of a single |
+function. Each function block defines the intermediate representation of the |
+function, consisting of basic blocks and instructions. If constants are used |
+within instructions, they are defined in a *constants block*, nested within the |
+corresponding function block. |
+ |
+All function blocks are associated with a corresponding function address. This |
+association is (again) positional rather than explicit. That is, the Nth |
+function block in a module block corresponds to the Nth defining (rather than |
+declared) function address record in the module block. |
+ |
+Hence, within a function block, there is no explicit reference to the |
+function address the block defines. For readability, PNaClAsm uses the |
+corresponding function heading, associated with the corresponding |
+function address record, even though that data does not appear in the |
+corresponding records. |
+ |
+PNaCl Records |
+============= |
+ |
+A PNaCl record is a non-empty sequence of unsigned, 64-bit, integers. A record |
+is identified by the record *code*, which is the first element in the |
+sequence. Record codes are unique within a specific kind of block, but are not |
+necessarily unique across different kinds of blocks. The record code acts as the |
+variant discriminator (i.e. tag) within a block, to identify what kind of record |
+it is. |
+ |
+Record codes that are local to a specific kind of block are small values |
+(staring from zero). In an ideal world, they would be a consecutive sequence of |
Jim Stichnoth
2014/06/06 18:24:49
starting
Karl
2014/06/30 22:09:04
Done.
|
+integers, starting at zero. However, the reality is that PNaCl records evolved |
+over time (and actually started as LLVM records [ref]). For backwards |
+compatibility, old numbers have not been reused, leaving gaps in the actual |
+record code values used. |
+ |
+Global record codes are record codes that have the same meaning in multiple |
+kinds of block. To separate global record codes from local record codes, large |
+values are used. Currently there are four global record codes. To make these |
+cases clear, and to leave room for lots of future growth in PNaClAsm, these |
+special records have record codes close to the value 2**16. Note: Well-formed |
+PNaCl bitcode files do not have record codes >= 2**16. |
+ |
+A PNaCl record is denoted as follows: |
+ |
+.. naclcode:: |
+ |
+ a: <v0, v1, ... , vN> |
+ |
+The value *v0* is the record code. The remaining values, *v1* through *vN*, are |
+parameters that fill in additional information needed by the construct it |
+represents. All records must have a record code. Hence, empty PNaCl records are |
+not allowed. |
+ |
+While most records (for a given record code) are of the same length, it is not |
+true of all record codes. Some record codes can have arbitrary length. In |
+particular, function type signatures, call instructions, phi nodes, switch |
+instructions, and global variable initialization records all have variable |
+length. |
jvoung (off chromium)
2014/06/06 20:09:14
Should this reference a section that describes how
Karl
2014/06/30 22:09:04
Added a couple of sentences trying to clarify this
|
+ |
+Records are converted to bit sequences using an abbreviation. Let *a* the the index |
Jim Stichnoth
2014/06/06 18:24:50
the the --> be the
also, 80-col
Karl
2014/06/30 22:09:05
Removed paragraph. presented too early to be usefu
|
+identifying the abbreviation that is used to convert the record to a sequence of |
+bits. If a user-defined abbreviation *%aA* (or *@aA* if global) is specified in |
+the syntax, then *a = AbbrevIndex(%aA)*. |
+ |
+The PNaCl bitcode writer, which converts records to bit sequences, does this by |
+writing out the abbreviation index used to encode the record, followed by the |
+contents of the record. The details of this are left to section on abbreviations |
Jim Stichnoth
2014/06/06 18:24:47
to section --> to the section
(though this will pr
Karl
2014/06/30 22:09:03
Done.
|
+[ref]. However, at the record level, one important aspect of this appears in |
+block enter records. These records must define how many bits are required to |
+hold abbreviation indices associated with records of that block. |
+ |
+There are 4 predefined (default) abbreviation indices, used as the default |
+abbreviations for PNaCl records. They are: |
+ |
+0 |
+ Abbreviation index for the abbreviation used to bit-encode an exit block |
+ record. |
+ |
+1 |
+ Abbreviation index for the abbreviation used to bit-encode a enter block |
Jim Stichnoth
2014/06/06 18:24:47
a enter --> an enter
Karl
2014/06/30 22:09:04
Done.
|
+ record. |
+ |
+2 |
+ Abbreviation index for the abbreviation used to bit-encode a user-defined |
jvoung (off chromium)
2014/06/06 20:09:14
I don't know if it's too redundant, or clear as is
Karl
2014/06/30 22:09:04
I agree this isn't obvious. Added a sentence to he
|
+ abbreviation record. |
+ |
+3 |
+ Abbreviation index for the default abbreviation to bit-encode all other |
+ records in the bitcode file. |
+ |
+A block may (in addition), define a list of block specific, user-defined, |
+abbreviations (of length *U*). The number of bits *B* specified for an enter |
+record must be sufficiently large such that |
+ |
+.. naclcode:: |
+ |
+ 2**B >= U + 4 |
+ |
+In addition, the upper limit for B is 32. |
+ |
+PNaClAsm requires that you specify the number of bits needed to read |
+abbreviations as part of the enter block record. This allows the PNaCl bitcode |
+reader/writer to use the specified number of bits to encode abbreviation |
+indices. |
+ |
+Conventions for describing records |
jvoung (off chromium)
2014/06/06 20:09:14
nit: consistency in capitalization of section head
|
+================================== |
+ |
+PNaClAsm is the textual representation of PNaCl records. Each PNaCl record is |
+described by a corresponding PNaClAsm construct. These constructs are described |
+using syntax rules, and semantics on how they are converted to records. The |
jvoung (off chromium)
2014/06/06 20:09:14
This is the first time "the parser" is mentioned.
Karl
2014/06/30 22:09:04
Tried to clear up that there is "global" state tha
|
+parser also has state, that is updated after the record is processed. These |
Jim Stichnoth
2014/06/06 18:24:49
either "state that" or "state, which"
|
+state updates are part of the semantics of the corresponding record construct. |
+ |
+For each PNaCl construct, we define multiple subsections. The **Syntax** |
+subsection defines a syntax rule for the construct. The **Record** subsection |
+defines the corresponding record associated with the syntax rule. The |
+**Semantics** subsection describes the semantics associated with the record, in |
+terms of data within the parse state and the corresponding syntax. It also |
+includes other high-level semantics, when appropriate. |
+ |
+The **Constraints** subsection (if present) defines any constraints associated |
+with the construct. The **Updates** subsection (if present) defines how the |
+parse state is updated when the construct is parsed. The **Examples** |
+subsection gives one (or more) examples of using the corresponding PNaClAsm |
+construct. |
+ |
+Some semantics subsections use functions to compute values. The meaning of |
+functions can be found in *Support Functions* [ref]. |
+ |
+Within a syntax rule, there may specifications about abbreviations. These |
jvoung (off chromium)
2014/06/06 20:09:14
"there may be specifications" ?
|
+abbreviation specifications, if allowed, are at the end of the construct, and |
+enclosed in *<* and *>* brackets. These abbreviation specifications are optional |
+in the syntax, and can be omitted. If they are used, the abbreviation brackets |
+are part of the actual syntax of the construct. To make it clear that |
+abbreviation specifications are optional, syntax rules separate abbreviation |
+specifications using plenty of whitespace. |
+ |
+Abbreviation specifications consist of user-defined abbreviations, abbreviation |
+identifiers, and the number of bits required to represent abbreviations in a |
+block. These notations appear, as appropriate, in the corresponding syntax |
+rules. |
+ |
+The most common abbreviation syntax is the corresponding abbreviation identifier |
+to use to read/write the corresponding record. In such cases, if the specified |
+abbreviation identifier is omitted, the corresponding default abbreviation will |
+be used by the PNaCl reader/writer. |
+ |
+Also, within the syntax rule, all alphabetic characters are lower case unless |
+they appear within a literal value. Hence, if we mix lower and upper case |
+letters within a name appearing in a syntax rule, the lower case letters are |
+literal while the upper case sequence of letters denote (rule specific) |
jvoung (off chromium)
2014/06/06 20:09:13
Earlier "all alphabetic characters are lower case
Karl
2014/06/30 22:09:04
Rewrote. Hopefully clarified.
|
+values. If an upper case sequence of letters is followed by digits, the |
+corresponding embedded name includes both the upper case letters and the digits. |
+The valid values for each of these names will be defined in the corresponding |
+semantics subsection. |
+ |
+For example, consider the following syntax rule: |
+ |
+.. naclcode:: |
+ |
+ %vN = add T O1, O2; <A> |
+ |
+This rule defines a PNaClAsm add instruction. This construct defines an |
+instruction that adds two values (*O1* and *O2*) to generate instruction |
+value *%vN*. The types of the arguments, and the result, are all of type |
+*T*. Since abbreviation ID *A* is present, the record is encoded using that |
+abbreviation. |
+ |
+To be concrete, the syntactic rule above defines the structure of the following |
+PNaClAsm examples. |
+ |
+.. naclcode:: |
+ |
+ %v10 = add i32 %v1, %v2; <@a5> |
+ %v11 = add i32 %v10, %v3; |
+ |
+In addition to specifying the syntax, each syntax rule also specifies the |
+contents of the corresponding record in the corresponding record subsection. In |
+simple cases, the elements of the corresponding record are predefined (literal) |
+constants. Otherwise the record element is a name that is defined by the other |
+subsections associated with the construct. |
+ |
+Factorial Example |
+================= |
+ |
+This section provides a simple example of a PNaCl bticode file. Its contents |
Jim Stichnoth
2014/06/06 18:24:49
bitcode
Karl
2014/06/30 22:09:04
Done.
|
+describes a bitcode file that only defines a function to compute the factorial |
Jim Stichnoth
2014/06/06 18:24:47
describe
|
+value of a number. |
+ |
+In C, the factorial function can be defined as: |
+ |
+.. naclcode:: |
+ |
+ int fact(int n) { |
+ if (n == 0) return 1; |
+ return n * fact(n-1); |
+ } |
+ |
+Compiling this into a PEXE file, and dumping out its contents with utility |
Jim Stichnoth
2014/06/06 18:24:48
Just checking - are we calling this a PEXE file in
Karl
2014/06/30 22:09:04
Good point. I should call it the bitcode file, not
|
+*pnacl-bcdis*, the corresponding output is: |
+ |
+.. naclcode:: |
+ |
+ 0:0|<65532, 80, 69, 88, 69, 1, 0,|Magic Number: 'PEXE' (80, 69, 88, 69) |
+ | 8, 0, 17, 0, 4, 0, 2, 0, 0, |PNaCl Version: 2 |
+ | 0> | |
+ 16:0|1: <65535, 8, 3> |module { // BlockID = 8 |
+ 24:0| 3: <1, 1> | version 1; |
+ 26:5| 1: <65535, 0, 2> | abbreviations { // BlockID = 0 |
+ 36:0| 0: <65534> | } |
+ 40:0| 1: <65535, 17, 4> | types { // BlockID = 17 |
jvoung (off chromium)
2014/06/06 20:09:13
Abbrev index bitwidth says "4", even though no use
Karl
2014/06/30 22:09:05
Thanks for noting this. I didn't realize that we s
|
+ 48:0| 3: <1, 4> | count 4; |
+ 50:6| 3: <7, 32> | @t0 = i32; |
+ 54:2| 3: <2> | @t1 = void; |
+ 56:2| 3: <21, 0, 0, 0> | @t2 = i32 (i32); |
+ 60:4| 3: <7, 1> | @t3 = i1; |
+ 63:2| 0: <65534> | } |
+ 64:0| 3: <8, 2, 0, 0, 0> | define external i32 @f0(i32); |
+ 68:7| 1: <65535, 19, 4> | globals { // BlockID = 19 |
+ 76:0| 3: <5, 0> | count 0; |
+ 78:6| 0: <65534> | } |
+ 80:0| 1: <65535, 14, 4> | valuesymtab { // BlockID = 14 |
+ 88:0| 3: <1, 0, 102, 97, 99, | @f0 : "fact"; |
+ | 116> | |
+ 96:6| 0: <65534> | } |
+ 100:0| 1: <65535, 12, 5> | function i32 @f0(i32 %p0) { |
+ | | // BlockID = 12 |
+ 108:0| 3: <1, 3> | blocks 3; |
+ 110:7| 1: <65535, 11, 4> | constants { // BlockID = 11 |
+ 120:0| 3: <1, 0> | i32: |
+ 122:6| 3: <4, 2> | %c0 = i32 1; |
+ 125:4| 3: <4, 0> | %c1 = i32 0; |
+ 128:2| 0: <65534> | } |
+ | | %b0: |
+ 132:0| 3: <28, 1, 2, 32> | %v0 = icmp eq i32 %c1, %c0; |
+ 137:1| 3: <11, 1, 2, 1> | br i1 %v0, %b1, %b2; |
+ | | %b1: |
+ 141:4| 3: <10, 3> | ret i32 %c0; |
+ | | %b2: |
+ 144:3| 3: <2, 4, 3, 1> | %v1 = sub i32 %p0, %c0; |
+ 148:6| 3: <34, 0, 6, 1> | %v2 = call i32 @f0(i32 %p0); |
+ 153:7| 3: <2, 6, 1, 2> | %v2 = mul i32 @f0, %v1; |
+ 158:2| 3: <10, 1> | ret i32 %v2; |
+ 161:1| 0: <65534> | } |
+ 164:0|0: <65534> |} |
+ |
+ |
+Note that there are three columns in this output. The first column contains the |
+bit positions of the records within the bitcode file. The second column contains |
+the sequence of records within the bitcode file. The third column contains the |
+corresponding PNaClAsm program. |
+ |
+Bit positions are defined by a pair *B:N*. *B* is the number of bytes, while *N* |
+is the bit offset within the *B+1* byte. Hence, the bit position (in bits) is: |
+ |
+.. naclcode:: |
+ |
+ B*8 + N |
+ |
+Hence, the first *header* record is at bit offset 0 (0*8+0). The second record |
+is at bit offset 128 (16*8+0). The third record is at bit offset 192 (24*8+0). |
+The fourth record is at bit offset 213 (26*8+5). |
+ |
+The header record is a sequence of 16 bytes, defining the contents of the first |
+16 bytes of the bitcode file. The first four bytes define the magic number of |
+the file. That is, 'PEXE'. All PEXE bitcode files begin with these four bytes. |
Jim Stichnoth
2014/06/06 18:24:50
the file, i.e. 'PEXE'.
Karl
2014/06/30 22:09:03
Done.
|
+Byte 13 defines the PNaCl bitcode version of the file. Currently, only version 2 |
jvoung (off chromium)
2014/06/06 20:09:13
Only byte 13, or byte 13, 14, 15, and 16?
Karl
2014/06/30 22:09:06
Simplified this to just state they shouldn't chang
|
+is allowed. |
jvoung (off chromium)
2014/06/06 20:09:14
What about the bytes in between (5 through 12)? Co
Karl
2014/06/30 22:09:06
Done.
|
+ |
+All but the header record has an abbreviation index associated with it. Since no |
+user-defined abbreviations are provided, all records use the default |
+abbreviation. |
+ |
+The types block (starting at bit address 40:0), defines 4 types: *i1*, *i32*, |
+*void*, and function signature *i32(i32)*. |
+ |
+Bit address 64:0 declares the factorial function address @f0, and its |
+corresponding type signature. Bit address 88:0 associates the name "fact" with |
+function address @f0. |
+ |
+Bit address 100:0 defines the function block that implemnts function "fact". The |
Jim Stichnoth
2014/06/06 18:24:47
implements
|
+entry point is %b0 (at bit address 132:0). It uses the 32-bit integer constants |
+1 and 0 (defined at bit addresses 122:6 and 125:4). Bit address 132:0 defines an |
+equality comparison of the argument %p0 with 0 (constant %c1). Bit address 137:1 |
+defines a conditional branch. If the result of the previous comparison (%v0) is true, |
Jim Stichnoth
2014/06/06 18:24:46
80-col
|
+the program will branch to block %b1. Otherwise it will branch to block %b2. |
+ |
+Bit address 141:4 returns constant 1 (%c0) when the input parameter is 0. |
+Instructions between bit address 144:3 and 158:2 compute and return "n * |
+fact(n-1)". |
jvoung (off chromium)
2014/06/06 20:09:13
The second column isn't really described in this e
Karl
2014/06/30 22:09:05
yes.
|
+ |
+Parse State |
+=========== |
+ |
+This section describes the parse state of the PNaClAsm assembler. It is used to |
+define contextual data that is carried between records. The following |
+subsections describe each element of the parse state. |
+ |
+Typing |
+------ |
+ |
+Associated with most identifiers is a type. This type defines what type the |
+corresponding value has. It is defined by the (initially empty) map |
+ |
+.. naclcode:: |
+ |
+ TypeOf: ID -> Type |
+ |
+For each type in the *types block* [ref], a corresponding inverse map |
+ |
+.. naclcode:: |
+ |
+ TypeID: Type -> ID |
+ |
+is maintained to convert syntactic types to the corresponding type ID. |
+ |
+Note: This document assumes that map *TypeID* is automatically maintained during |
+updates to map *TypeOf* (when given a type ID). Hence, *updates* subsections |
+will not contain assignments to this map. |
+ |
+Associated with each function identifier is its type signature. This is |
+different than the type of the function identifier, since function identifiers |
jvoung (off chromium)
2014/06/06 20:09:14
would it help to say that "..., since function ide
Karl
2014/06/30 22:09:02
Done.
|
+are pointers (and always implemented as a 32-bit integer). |
+ |
+Function type signatures are maintained using: |
+ |
+.. naclcode:: |
+ |
+ TypeOfFcn: ID -> Type |
+ |
+In addition, if a function address has an implementing block, there is a |
+corresponding implementation associated with the function address. To capture |
+this association, we use the set: |
+ |
+.. naclcode:: |
+ |
+ DefiningFcnIDs: set(ID) |
+ |
+ID Counters |
+----------- |
+ |
+Each block defines one (or more) kinds of values. Value indices are generated |
+sequentially, starting at zero. To capture this, the following counters are |
+defined: |
+ |
+NumTypes |
+ The number of types defined so far (in the types block) |
+ |
+NumFuncAddresses |
+ The number of function addresses defined so far (in the module block). |
+ |
+NumDefinedFcnAddresses |
jvoung (off chromium)
2014/06/06 20:09:14
How is this different from NumFuncAddresses? Updat
Karl
2014/06/30 22:09:04
These are two different values. Added additional s
|
+ The number of defining function addresses defined so far (in the module |
+ block). |
+ |
+NumFuncImpls |
+ The number of implemented functions defined so far (in the module block). |
+ |
+NumGlobalAddresses |
+ The number of global variable/constant addresses defined so far (in the |
+ globals block). |
+ |
+NumParams |
+ The number of parameters defined for a function. |
+ |
+NumFcnConsts |
+ The number of constants defined in a function. |
jvoung (off chromium)
2014/06/06 20:09:13
so far?
Depends on how you define the update rule
Karl
2014/06/30 22:09:03
Done.
|
+ |
+NumBasicBlocks |
+ The number of basic blocks defined so far (within a function block). |
+ |
+NumValuedInsts |
+ The number of instructions, generating values, defined so far (within a |
+ function block). |
+ |
+Size Variables |
+-------------- |
+ |
+A number of blocks define expected sizes of constructs. These sizes are recorded |
+in the following size variables: |
+ |
+ExpectedBasicBlocks |
+ The expected number of basic blocks within a function implementation. |
+ |
+ExpectTypes |
+ The expected number of types defined in the types block. |
+ |
+ExpectedGlobals |
+ The expected number of global variable/constant addresses in the globals |
+ block. |
+ |
+ExpectedInitializers |
+ The expected number of initializers for a global variable/constant address in |
+ the globals block. |
+ |
+Other Variables |
+--------------- |
+ |
+EnclosingFcnID |
+ The function ID of the function block being processed. |
+ |
+Global records |
+============== |
+ |
+There are four global PNaCl records, each having its own record code. These |
+global records are: |
+ |
+Header |
+ The header record is the first record of a PNaCl bitcode file, and identifies |
+ the file's magic number, as well as the bitcode version it uses. The record |
+ defines the sequence of bytes that make up the header and uniquely identifies |
+ the file as a PNaCl bitcode file. |
+ |
+Enter |
+ An enter record defines the beginning of a block. Since blocks can be nested, |
+ one can appear inside other blocks, as well as at the top level. |
+ |
+Exit |
+ An exit record defines the end of a block. Hence, it must appear in every |
+ block, to end the block. |
+ |
+Abbreviation |
+ An abbreviation record defines a user-defined abbreviation to be applied to |
+ records within blocks. Abbreviation records appearing in the abbreviations |
+ block define global abbreviations. All other abbreviations are local to the |
+ block they appear in, and can only be used in that block. |
+ |
+All special records can't have user-defined abbreviations associated with |
+them. The default abbreviation is always used. |
+ |
+The following subsections define valid special records, other than abbreviation |
+records. Abbreviation records are described in the Abbreviations [ref] section. |
+ |
+Header Record |
+------------- |
+ |
+The header record must be the first record in the file. It is the only record in |
+the bitcode file that doesn't have a corresponding construct in |
+PNaClAsm. |
+ |
+**Syntax** |
+ |
+There is no syntax for header records in PNaClAsm. It is automatically inserted |
+by the PNaCl bitcode writer. |
+ |
+**Record** |
+ |
+.. naclcode:: |
+ |
+ <65532, 80, 69, 88, 69, 1, 0, 8, 0, 17, 0, 4, 0, 2, 0, 0, 0> |
+ |
+**Semantics** |
+ |
+The header record defines the initial sequence of bytes that must appear at the |
+beginning of all (PNaCl bitcode version 2) files. That sequence is the list of |
+bytes inside the record (excluding the record code). As such, it uniquely |
+identifies PNaCl bitcode files. |
+ |
+**Examples** |
+ |
+There are no examples for the header record, since it is not part of PNaClAsm. |
+ |
+Enter Block Record |
+------------------ |
+ |
+Block records can be top-level, as well as nested in other blocks. Blocks must |
+begin with an *enter* record, and end with an *exit* record. |
+ |
+**Syntax** |
+ |
+.. naclcode:: |
+ |
+ N { <B> |
+ |
+**Record** |
+ |
+.. naclcode:: |
+ |
+ 1: <65535, ID, B> |
+ |
+**Semantics** |
+ |
+Enter block records define the beginning of a block. *B*, if present, is the |
+number of bits needed to represent all possible abbreviation indices used within |
+the block. If omitted, B=2 is assumed. |
+ |
+The block *ID* value is dependent on the name *N*. Valid names and corresponding |
+*BlockID* values are defined as follows: |
+ |
+============= ======== |
+N Block ID |
+============= ======== |
+abbreviations 0 |
+constants 11 |
+function 12 |
+globals 19 |
+module 8 |
+types 17 |
+valuesymtab 14 |
+============= ======== |
+ |
+Note: For readability, PNaClAsm allows a more readable form of a function block |
+enter record. See *function blocks* [ref] for more details. |
+ |
+**Examples** |
+ |
+.. naclcode:: |
+ |
+ module { |
+ types { |
+ count: 0; |
+ } |
+ globals { |
+ count: 0; |
+ } |
+ } |
+ |
+This example defines a module, types, and globals block. Both the type and the |
+globals block appear within the module block. |
+ |
+The corresponding records are: |
+ |
+.. naclcode:: |
+ |
+ 1: <65535, 8, 2> |
+ 1: <65535, 17, 2> |
+ 3: <1, 0> |
+ 0: <65534> |
+ 1: <65535, 19, 2> |
+ 3: <5, 0> |
+ 0: <65534> |
+ 0: <65534> |
+ |
+Exit Block Record |
+----------------- |
+ |
+Block records can be top-level, as well as nested, records. Blocks must begin |
+with an *enter* record, and end with an *exit* record. |
+ |
+**Syntax** |
+ |
+.. naclcode:: |
+ |
+ } |
+ |
+**Record** |
+ |
+.. naclcode:: |
+ |
+ 0: <65534> |
+ |
+**Semantics** |
+ |
+All exit records are identical, no matter what block they are ending. An exit |
+record defines the end of the block. |
+ |
+**Examples** |
+ |
+.. naclcode:: |
+ |
+ module { |
+ types { |
+ count: 0; |
+ } |
+ globals { |
+ count: 0; |
+ } |
+ } |
+ |
+This example defines a module, types, and globals block. Both the type and the |
+globals block appear within the module block. |
+ |
+The corresponding records are: |
+ |
+.. naclcode:: |
+ |
+ 1: <65535, 8, 2> |
+ 1: <65535, 17, 2> |
+ 3: <1, 0> |
+ 0: <65534> |
+ 1: <65535, 19, 2> |
+ 3: <5, 0> |
+ 0: <65534> |
+ 0: <65534> |
+ |
jvoung (off chromium)
2014/06/06 20:09:14
Description for the remaining global record (abbre
Karl
2014/06/30 22:09:04
This was already stated in the enclosing section.
|
+Types Block |
+=========== |
+ |
+The types block defines all types used in a program. It must appear in the |
+module block, before any function address records, the globals block, the |
+valuesymtab block, and any function blocks. |
+ |
+All types used in a program must be defined in the types block. Many PNaClAsm |
+constructs allow one to use explicit type names, rather than the type |
+identifiers defined by this block. However, they are internally converted to the |
+corresponding type identifer in the types block. Hence, the requirement that the |
+types block must appear early in the module block. |
+ |
+Each record in the types block defines a type used by the program. Types can be |
+broken into the following groups: |
+ |
+Primitive Value types |
+ Defines the set of base types for values. This includes various sizes of |
+ integral and floating types. |
+ |
+Void type |
+ A primitive type that doesn't represent any value and has no size. |
+ |
+Function types |
+ The type signatures of functions. |
+ |
+Vector type |
+ Defines vectors of primitive types. |
+ |
+In addition, any type that is not defined using another type is a primitive |
+type. All other types (i.e. function and vector) are composite types. |
+ |
+Types must be defined in a topological order, causing primitive types to appear |
+before the composite types that use them. Each type must be unique. There are no |
+additional restrictions on the order that types can be defined in a types block. |
+ |
+The following subsections introduce each valid PNaClAsm type, and the |
+corresponding PNaClAsm construct that defines the type. Types not defined in the |
+types block, can't be used in a PNaCl program. |
+ |
+The first record of a types block must be a *count* record, defining how many |
+types are defined by the types block. All remaining records defines a type. The |
+following subsections define valid records within a types block. The order of |
+type records is important. The position of each defining record implicitly |
+defines the type ID that will be used to denote that type, within other PNaCl |
+records of the bitcode file. |
+ |
+To make this more concrete, consider the following example types block: |
+ |
+.. naclcode:: |
+ |
+ types { |
+ count: 4; |
+ @t0 = void; |
+ @t1 = i32; |
+ @t2 = float; |
+ @t3 = void (i32, float); |
+ } |
+ |
+This example defines a types block that defines four type IDs: |
+ |
+0. The void type. |
+1. A 32-bit integer type. |
+2. A 32-bit floating type. |
+3. A function, taking 32-bit integer and float arguments that returns void. |
+ |
+Note that the order defines the corresponding identifier that will be used for |
+that type, and is based on the position of the type within the types |
+record. Hence, the assignment to identifier *@tN* can never appear before the |
+assignment to identifier *@tN-1*. Further, if type identifier *@tN* is assigned, |
+it must appear immediately after the assignment to identifier *@tN-1*. |
+ |
+Count Record |
+------------ |
+ |
+The *count record* defines how many types are defined in the types |
+block. Following the types count record are records that define types used by |
+the PNaCl program. |
+ |
+**Syntax** |
+ |
+.. naclcode:: |
+ |
+ count: N; <A> |
+ |
+**Record** |
+ |
+ AA: <1, N> |
+ |
+**Semantics** |
+ |
+This construct defines the number of types used by the PNaCl program. *N* is |
+the number of types defined in the types block. It is an error to define more |
+(or fewer) types than value *N*, within the enclosing types block. *A* is the |
+(optional) abbreviation associated with the record. |
+ |
+**Constraints** |
+ |
+.. naclcode:: |
+ |
+ AA == AbbrevIndex(A) |
+ 0 == NumTypes |
+ |
+**Updates** |
+ |
+.. naclcode:: |
+ |
+ ExpectedTypes = N; |
+ |
+**Examples** |
+ |
+.. naclcode:: |
+ |
+ types { |
+ count: 2; |
+ @t0 = float; |
+ @t1 = i32; |
+ } |
+ |
+This example defines two types. A 32 bit integer and a 32 bit floating types. |
+The corresponding records are: |
+ |
+.. naclcode:: |
+ |
+ 1: <65535, 17, 2> |
+ 3: <1, 2> |
+ 3: <3> |
+ 3: <7, 32> |
+ 0: <65534> |
+ |
+Void Type |
+--------- |
+ |
+The *void* type record defines the void type, which corresponds to the type that |
+doesn't define any value, and has no size. |
+ |
+**Syntax** |
+ |
+.. naclcode:: |
+ |
+ @tN = void; <A> |
+ |
+**Record** |
+ |
+.. naclcode:: |
+ |
+ AA: <2> |
+ |
+**Semantics** |
+ |
+The void type record defines the type that has no values and has no size. *A* |
+is the (optional) abbreviation associated with the record. |
+ |
+**Constraints** |
+ |
+.. naclcode:: |
+ |
+ AA == AbbrevIndex(A) |
+ N == NumTypes |
+ NumTypes < ExpectedTypes |
+ |
+**Updates** |
+ |
+.. naclcode:: |
+ |
+ ++NumTypes; |
+ TypeOf(@tN) = void; |
+ |
+**Examples** |
+ |
+.. naclcode:: |
+ |
+ @t0 = void; |
+ |
+defines the record |
+ |
+.. naclcode:: |
+ |
+ 3: <2> |
+ |
+Integer Types |
+------------- |
+ |
+PNaClAsm allows integral types for various bit sizes. Valid bit sizes are 1, 8, |
+16, 32, and 64. Integers can be signed or unsigned, but the signed component of |
+an integer is not specified by the type. Rather, individual instructions |
+determine whether the value is assumed to be signed or unsigned. |
+ |
+It should be noted that in PNaClAsm, all pointers are implemented as 32-bit |
+(unsigned) integers. There isn't a separate type for pointers. The only way to |
+tell that a 32-bit integer is a pointer, is when it is used in an instruction |
+that requires a pointer (such as load and store instructions). |
+ |
+**Syntax** |
+ |
+.. naclcode:: |
+ |
+ @tN = iB; <A> |
+ |
+**Record** |
+ |
+ AA: <7, B> |
+ |
+**Semantics** |
+ |
+An integer type record defines an integral type. *B* defines the number of bits |
+of the integral type. *A* is the (optional) abbreviation associated with the |
+record. |
+ |
+**Constraints** |
+ |
+.. naclcode:: |
+ |
+ AA == AbbrevIndex(A) |
+ N == NumTypes |
+ NumTypes < ExpectedTypes |
+ B in {1, 8, 16, 32, 64} |
+ |
+**Updates** |
+ |
+.. naclcode:: |
+ |
+ ++NumTypes; |
+ TypeOf(@tN) = iB; |
+ |
+**Examples** |
+ |
+.. naclcode:: |
+ |
+ @t1 = i32; |
+ @t2 = i1; |
+ @t3 = i64; |
+ |
+defines the records |
+ |
+.. naclcode:: |
+ |
+ 3: <7, 32> |
+ 3: <7, 1> |
+ 3: <7, 64> |
+ |
+32-Bit Floating Type |
+-------------------- |
+ |
+PNaClAsm allows computation on 32-bit floating values. A floating type record |
jvoung (off chromium)
2014/06/06 20:09:13
"floating type record" --> "float type record" ?
|
+defines the 32-bit floating type. |
+ |
+**Syntax** |
+ |
+.. naclcode:: |
+ |
+ @tN = float; <A> |
+ |
+**Record** |
+ |
+.. naclcode:: |
+ |
+ AA: <3> |
+ |
+**Semantics** |
+ |
+A floating type record defines the 32-bit floating type. *A* is the (optional) |
+abbreviation associated with the record. |
+ |
+**Constraints** |
+ |
+.. naclcode:: |
+ |
+ AA == AbbrevIndex(A). |
+ N == NumTypes |
+ NumTypes < ExpectedTypes |
+ |
+**Updates** |
+ |
+.. naclcode:: |
+ |
+ ++NumTypes; |
+ TypeOf(@tN) = float; |
+ |
+**Examples** |
+ |
+.. naclcode:: |
+ |
+ @t5 = float; |
+ |
+defines the record |
+ |
+.. naclcode:: |
+ |
+ 3: <3> |
+ |
+64-bit Floating Type |
+-------------------- |
+ |
+PNaClAsm allows computation on 64-bit floating values. A double type record |
+defines the 64-bit floating type. |
+ |
+**Syntax** |
+ |
+.. naclcode:: |
+ |
+ @tN = double; <A> |
+ |
+**Record** |
+ |
+.. naclcode:: |
+ |
+ AA: <4> |
+ |
+**Semantics** |
+ |
+A double type record defines the 64-bit floating type. *A* is the (optional) |
+abbreviation associated with the record. |
+ |
+**Constraints** |
+ |
+.. naclcode:: |
+ |
+ AA == AbbrevIndex(A) |
+ N == NumTypes |
+ NumTypes < ExpectedTypes |
+ |
+**Updates** |
+ |
+.. naclcode:: |
+ |
+ ++NumTypes; |
+ TypeOf(@tN) = double; |
+ |
+**Examples** |
+ |
+.. naclcode:: |
+ |
+ @t3 = double; |
+ |
+defines the record |
+ |
+.. naclcode:: |
+ |
+ 3: <4> |
+ |
+Vector Types |
+------------ |
+ |
+TODO(kschimpf) <N x T> |
+ |
+TODO(kschimpf) Define integral and floating vector types. |
+ |
+Function Type |
+------------- |
+ |
+The *function* type can be thought of as a function signature. It consists of a |
+return type, and a (possibly empty) list of formal parameter types. |
+ |
+**Syntax** |
+ |
+.. naclcode:: |
+ |
+ %tN = RT (T1, ... , TM) <A> |
+ |
+**Record** |
+ |
+.. naclcode:: |
+ |
+ AA: <21, 0, IRT, IT1, ... , ITM> |
+ |
+**Semantics** |
+ |
+The function type defines the signature of a function. *RT* is the return type |
+of the function, while types *T1* through *TM* are the types of the |
+arguments. Indicies to the corresponding type identifiers is stored in the |
Jim Stichnoth
2014/06/06 18:24:48
are stored
Jim Stichnoth
2014/06/06 18:24:48
Indices
Karl
2014/06/30 22:09:03
Done.
Karl
2014/06/30 22:09:06
Done.
|
+corresponding record. |
+ |
+The return value must either be a primitive type, type *void*, or a vector type. |
+Parameter types can be a primitive or vector type. |
+ |
+For the integral types, only i32 and i64 can be used for a return or parameter |
+type. All other integral types are not allowed. |
+ |
+ |
+**Constraints** |
+ |
+.. naclcode:: |
+ |
+ AA = AbbrevIndex(A) |
+ M >= 0 |
+ IRT = AbsoluteIndex(TypeID(RT)) |
+ IT1 = AbsoluteIndex(TypeID(T1)) |
+ ... |
+ ITM = AbsoluteIndex(TypeID(TM)) |
+ N == NumTypes |
+ NumTypes < ExpectedTypes |
+ |
+**Updates** |
+ |
+.. naclcode:: |
+ |
+ ++NumTypes; |
+ TypeOf(@tN) = RT (T1, ... , TM) |
+ |
+**Examples** |
+ |
+The following example defines two function signatures (*@t4* and *@t5*): |
+ |
+.. naclcode: |
+ |
+ types { |
+ count: 6; |
+ @t0 = i32; |
+ @t1 = i64; |
+ @t2 = float; |
+ @t3 = void; |
+ @t4 = void (i32, float, i64); |
+ @t5 = i32(); |
+ } |
+ |
+The corresponding records are: |
+ |
+.. naclcode:: |
+ |
+ 1: <65535, 17, 2> |
+ 3: <1, 6> |
+ 3: <7, 32> |
+ 3: <7, 64> |
+ 3: <3> |
+ 3: <2> |
+ 3: <21, 3, 0, 2, 1> |
+ 3: <21, 0> |
+ 0: <65534> |
+ |
+Globals block |
+============= |
+ |
+The globals block defines global addresses of variables and constants, used by |
+the PNaCl program. It also defines the memory associated with the global |
+addresses, and how to initialize each global variable/constant. It must appear |
+in the module block. It must appear after the types block, as well as after all |
+function address records. But, it must also appear before the valuesymtab block, |
+and any function blocks. |
+ |
+The globals block begins with a count record, defining how many global addresses |
+are defined by the PNaCl program. It is then followed by a sequence of records |
+that defines how each global address is initialized. |
+ |
+The standard sequence, for defining global addresses, begins with a global |
+address record. It is then followed by a sequence of records defining how the |
+global address is initialized. If the initializer is simple, a single record is |
+used. Otherwise, the initializer is preceded with a compound record, specifying |
+a number *N*, followed by sequence of *N* simple initializer records. |
+ |
+The size of the memory referenced by each global address is defined by its |
+initializer records. All simple initializer records define a sequence of |
+bytes. A compound initializer defines the sequence of bytes by concatenating the |
+corresponding sequence of bytes for each of its simple initializer records. |
+ |
+For notational convenience, PNaClAsm begins a compound record with a "{", and |
+inserts a "}" after the last initializer record associated compound record. This |
+latter "}" does not correspond to any record. It is implicitly assumed by the |
+size specified in the compound record, and is added only to improve readability. |
+ |
+Explicit alignment is specified for global addresses, and must be a power |
+of 2. If the alignment is 0, the alignment of the global is set by the target to |
+whatever it feels convenient. If the value is greater than zero, the global is |
+forced to have exactly that alignment. |
+ |
+For example, consider the following: |
+ |
+.. naclcode:: |
+ |
+ globals { |
+ count: 2; |
+ const @g0 = |
+ zerofill 8; |
+ var @g1 = |
+ initializers 2 { |
+ {1, 2, 3, 4}, |
+ zerofill 2; |
+ } |
+ } |
+ |
+ |
+TODO: Generate a pnacl-dis output to show relationship? |
+ |
+The corresponding records are: |
+ |
+.. naclcode:: |
+ |
+ 1: <65535, 19, 2> |
+ 3: <5, 2> |
+ 3: <0, 0, 1> |
+ 3: <2, 8> |
+ 3: <0, 0, 0> |
+ 3: <1, 2> |
+ 3: <3, 1, 2, 3, 4> |
+ 3: <2, 2> |
+ 0: <65534> |
+ |
+Count Record |
+------------ |
+ |
+The count record defines the number of global addresses used by the PNaCl |
+program. |
+ |
+**Syntax** |
+ |
+.. naclcode:: |
+ |
+ count: N; <A> |
+ |
+**Record** |
+ |
+.. naclcode:: |
+ |
+ AA: <5, N> |
+ |
+**Semantics** |
+ |
+This record must appear first in the globals block. The count record defines |
+the number of global addresses used by the program. *A* is the (optional) |
+abbreviation associated with the record. |
+ |
+**Constraints** |
+ |
+.. naclcode:: |
+ |
+ AA = AbbrevIndex(A) |
+ |
+**Updates** |
+ |
+.. naclcode:: |
+ |
+ ExpectedGlobals = N; |
+ ExpectedInitializers = 0; |
+ |
+Global Variable Addressses |
+-------------------------- |
+ |
+A global variable address record defines a global address to global data. The |
+global variable address record must be immediately followed by initializer |
+record(s) that define how the corresponding global variable is initialized. |
+ |
+**Syntax** |
+ |
+.. naclcode:: |
+ |
+ var @gN, align V = <A> |
+ var @gN = <A> |
+ |
+**Record** |
+ |
+.. naclcode:: |
+ |
+ AA: <0, VV, 0> |
+ |
+**Semantics** |
+ |
+A global variable address record defines a global address for a global variable. |
+*V* is the alignment to for the global variable. The alignment *V* clause can |
+be omitted if *V* is zero. *A* is the (optional) abbreviation associated with |
+the record. |
+ |
+It is assumed that the memory, referenced by the global variable address, can be |
+both read and written to. |
+ |
+**Constraints** |
+ |
+.. naclcode:: |
+ |
+ AA = AbbrevIndex(A) |
+ N = NumGlobalAddresses |
+ NumGlobalAddresses < ExpectedGlobals |
+ ExpectedInitializers = 0 |
+ VV = Log2(V+1) |
+ |
+**Updates** |
+ |
+.. naclcode:: |
+ |
+ ++NumGlobalAddresses; |
+ ExpectedInitializers = 1; |
+ TypeOf(@gN) = i32; |
+ |
+**Examples** |
+ |
+.. naclcode:: |
+ |
+ var @g0 = |
+ zerofill 8; |
+ var @g1 = |
+ {1, 2, 3, 4} |
+ |
+This example defines two global variable addresses, *@g0* and *@g1*. Both use |
+memory alignment of 0. *@g0* is an 8 byte variable initialized to zero. *@g1* |
+is a 4 byte variable, initialized by the sequence of bytes 1, 2, 3, and 4. |
+ |
+The corresponding records defined by the example above are: |
+ |
+.. naclcode:: |
+ |
+ 3: <0, 0, 0> |
+ 3: <2, 8> |
+ 3: <0, 0, 0> |
+ 3: <3, 1, 2, 3, 4> |
+ |
+Global Constant Addresses |
+------------------------- |
+ |
+A global constant address record defines an address corresponding to a global |
+constant that can't be modified by the program. The global constant address |
+record must be immediately followed by initializer record(s) that define how |
+the corresponding global constant is initialized. |
+ |
+**Syntax** |
+ |
+.. naclcode:: |
+ |
+ const @gN, align V = <A> |
+ const @gN = <A> |
+ |
+**Record** |
+ |
+.. naclcode:: |
+ |
+ AA: <0, VV, 1> |
+ |
+**Semantics** |
+ |
+A global constant address record defines a global address for a global constant. |
+*V* is the memory alignment for the global constant. *VV* is the corresponding |
+number of bits associated with alignment *V* (see *constraints*). The alignment |
+*V* caluse can be omitted if *V* is zero. *A* is the (optional) abbreviation |
Jim Stichnoth
2014/06/06 18:24:48
clause
Karl
2014/06/30 22:09:03
Done.
|
+associated with the record. |
+ |
+It is assumed that the memory, referenced by the global constant |
+address, is only read, and can't be written to. |
+ |
+Note that the only difference between a global variable address and a global |
+constant address record is the third element of the record. If the value is |
+zero, it defines a global variable address. If the value is one, it defines a |
+global constant address. |
+ |
+**Constraints** |
+ |
+.. naclcode:: |
+ |
+ AA = AbbrevIndex(A) |
+ N = NumGlobalAddresses |
+ NumGlobalAddresses < ExpectedGlobals |
+ ExpectedInitializers = 0 |
+ VV = Log2(V+1) |
+ |
+**Updates** |
+ |
+.. naclcode:: |
+ |
+ ++NumGlobalAddresses; |
+ ExpectedInitializers = 1; |
+ TypeOf(@gN) = i32; |
+ |
+**Examples** |
+ |
+.. naclcode:: |
+ |
+ const @g0 = |
+ zerofill 8; |
+ var @g1 = |
+ {1, 2} |
+ |
+This example defines two global constants, with global addresses *@g0* and |
+*@g1*. *@g0* is an 8 byte constant initialized to zero. *@g1* is a 2 byte |
+variable, initialized by the sequence of bytes 1 and 2. |
+ |
+The corresponding PNaCl bitcode records are: |
+ |
+.. naclcode:: |
+ |
+ 3: <0, 0, 1> |
+ 3: <2, 8> |
+ 3: <0, 0, 1> |
+ 3: <3, 1, 2> |
+ |
+Zerofill Initializer |
+-------------------- |
+ |
+The zerofill initializer record initializes a sequence of bytes, associated with |
+a global address, with zeros. |
+ |
+**Syntax** |
+ |
+.. naclcode:: |
+ |
+ zerofill N; <A> |
+ |
+**Record** |
+ |
+.. naclcode:: |
+ |
+ AA: <2, N> |
+ |
+**Semantics** |
+ |
+A zerofill initializer record intializes a sequence of bytes, associated with a |
+global address, with zeros. *A* is the (optional) abbreviation of the associated |
+record. |
+ |
+**Constraints** |
+ |
+.. naclcode:: |
+ |
+ AA = AbbrevIndex(A) |
+ ExpectedInitializers > 0; |
+ |
+**Updates** |
+ |
+.. naclcode:: |
+ |
+ --ExpectedInitializers; |
+ |
+**Examples** |
+ |
+.. naclcode:: |
+ |
+ const @g0 = |
+ zerofill 8; |
+ var @g1 = |
+ zerofill 4; |
+ |
+This example defines two global constants, with global addresses *@g0* and |
+*@g1*. The global memory associated with address *@g0*, is an eight byte value, |
+initialized to zero. The global memory associated with address *@g1*, is a 4 |
+byte value, initialized to zero. |
+ |
+The corresponding PNaCl records are: |
+ |
+.. naclcode:: |
+ |
+ 3: <0, 0, 1> |
+ 3: <2, 8> |
+ 3: <0, 0, 1> |
+ 3: <2, 4> |
+ |
+Data Initializer |
+---------------- |
+ |
+Data records define a sequence of bytes. These bytes define the initial value of |
+the contents of the corresponding memory. |
+ |
+**Syntax** |
+ |
+.. naclcode:: |
+ |
+ { B1 , .... , BN } <A> |
+ |
+**Record** |
+ |
+.. naclcode:: |
+ |
+ AA: <3, B1, ..., BN> |
+ |
+**Semantics** |
+ |
+A data record defines a sequence of bytes *B1* through *BN*, that initialize *N* |
+bytes of memory. *A* is the (optional) abbreviation associated with the record. |
+ |
+**Constraints** |
+ |
+.. naclcode:: |
+ |
+ AA = AbbrevIndex(A) |
+ ExpectedInitializers > 0 |
+ |
+**Updates** |
+ |
+.. naclcode:: |
+ |
+ --ExpectedInitializers; |
+ |
+**Examples** |
+ |
+.. naclcode:: |
+ |
+ const @g0 = |
+ {1, 2, 97, 36, 44, 88, 44} |
+ const @g1 = |
+ initializers 3 { |
+ {4, 5, 6, 7} |
+ reloc @f1; |
+ {99, 66, 22, 12} |
+ } |
+ |
+The corresponding PNaCl records are: |
+ |
+.. naclcode:: |
+ |
+ 3: <0, 0, 1> |
+ 3: <3, 1, 2, 97, 36, 44, 88, 44> |
+ 3: <0, 0, 1> |
+ 3: <1, 3> |
+ 3: <3, 4, 5, 6, 7> |
+ 3: <4, 1> |
+ 3: <3, 99, 66, 22, 12> |
+ |
+Relocation Initializer |
+---------------------- |
+ |
+A relocation initializer record allows one to define the initial value of a |
+global address with the value of another global address (i.e. either function, |
+variable, or constant). Since addresses are pointers, a relocation initializer |
+record defines 4 bytes of memory. |
+ |
+**Syntax** |
+ |
+.. naclcode:: |
+ |
+ reloc V; <A> |
+ |
+**Record** |
+ |
+.. naclcode:: |
+ |
+ AA: <4, VV> |
+ |
+**Semantics** |
+ |
+A relocation initializer record defines a 4-byte value containing the specified |
+global address *V*. *A* is the (optional) abbreviation associated with the |
+record. |
+ |
+**Constraints** |
+ |
+.. naclcode:: |
+ |
+ AA = AbbrevIndex(A) |
+ VV = AbsoluteIndex(V); |
+ ExpectedInitializers > 0 |
+ |
+**Updates** |
+ |
+.. naclcode:: |
+ |
+ --ExpectedInitializers; |
+ |
+**Examples** |
+ |
+.. naclcode:: |
+ |
+ var @g0 = |
+ initializers 3 { |
+ reloc @f1; |
+ reloc @g0; |
+ reloc @g10; |
+ } |
+ |
+This example defines global address *@g0*. It defines 12 bytes of memory, and is |
+initialized with three addresses *@f1*, *@g0*, and *@g10*. Note that all globals |
+can be used in a relocation initialization record, even if it isn't defined yet. |
+ |
+Assuming |
+ |
+.. naclcode:: |
+ |
+ 100 = AbsoluteIndex(@g0)) |
+ |
+The corresponding PNaCl bitcode records are: |
+ |
+.. naclcode:: |
+ |
+ 3: <0, 0, 0> |
+ 3: <1, 3> |
+ 3: <4, 1> |
+ 3: <4, 100> |
+ 3: <4, 110> |
+ |
+Subfield Relocation Initializer |
+------------------------------- |
+ |
+A subfield relocation initializer record allows one to define the initial value |
+of a global address with the value of another (non-function) global address |
+(i.e. either variable or constant), plus a constant. Since addresses are |
+pointers, a relocation initializer record defines 4 bytes of memory. |
+ |
+**Syntax** |
+ |
+.. naclcode:: |
+ |
+ reloc V + O; <A> |
+ reloc V - O; <A> |
+ |
+**Record** |
+ |
+.. naclcode:: |
+ |
+ AA: <4, VV, OOO> |
+ |
+**Semantics** |
+ |
+A relocation initializer record defines a 4-byte value containing the specified |
+global (non-function) address *V*, modified by the unsigned offset *O*. *OO* is |
+the corresponding signed offset. In the first form, *OO == O*. In the second |
+form, *OO == - O*. *A* is the (optional) abbreviation associated with the |
+record. *a* is the corresponding abbreviation index of *A*. When *A* is omitted, |
+*a=3*. |
+ |
+**Constraints** |
+ |
+.. naclcode:: |
+ |
+ AA = AbbrevIndex(A) |
+ VV == AbsoluteIndex(V) |
+ ExpectedInitializers > 0 |
+ OOO == SignRotate(OO) |
+ |
+**Updates** |
+ |
+.. naclcode:: |
+ |
+ --ExpectedInitializers; |
+ |
+**Examples** |
+ |
+.. naclcode:: |
+ |
+ var @g0 = |
+ initializers 3 { |
+ reloc @f1; |
+ reloc @g0 + 4; |
+ reloc @g10 - 3; |
+ } |
+ |
+This example defines global address *@g0*, and is initialized with three |
+pointers, addresses *@f1*, *@g0+4*, and *@g10-3*. Note that all global addresses |
+can be used in a relocation initialization record, even if it isn't defined |
+yet. Validity of the reference can be verified, since a global address *@g10* |
+must be smaller than the value specified in the globals count record. |
+ |
+Assuming |
+ |
+.. naclcode:: |
+ |
+ 100 = AbsoluteIndex(@g0)) |
+ |
+The corresponding PNaCl bitcode records are: |
+ |
+.. naclcode:: |
+ |
+ 3: <0, 0, 0> |
+ 3: <1, 3> |
+ 3: <4, 1> |
+ 3: <4, 100, 8> |
+ 3: <4, 110, 7> |
+ |
+Compound Initializer |
+-------------------- |
+ |
+The compound initializer record must immediately follow a global |
+variable/constant address record. It defines how many (non-compound) initializer |
+records are used to define the initializer. The size of the corresponding memory |
+is the sum of the bytes needed for each of the succeeding initializers. |
+ |
+**Syntax** |
+ |
+.. naclcode:: |
+ |
+ initializers N { <A> |
+ ... |
+ } |
+ |
+**Record** |
+ |
+.. naclcode:: |
+ |
+ AA: <1, N> |
+ |
+**Semantics** |
+ |
+Defines that the next *N* initializers should be associated with the global |
+address of the previous record. *A* is the (optional) abbreviation index |
+associated with the record. |
+ |
+**Constraints** |
+ |
+.. naclcode:: |
+ |
+ AA = AbbrevIndex(A) |
+ ExpectedInitializers == 1 |
+ |
+**Updates** |
+ |
+.. naclcode:: |
+ |
+ ExpectedInitializers = N; |
+ |
+**Examples** |
+ |
+.. naclcode:: |
+ |
+ const @g1 = |
+ initializers 3 { |
+ {4, 5, 6, 7} |
+ reloc @f1; |
+ {99, 66, 22, 12} |
+ } |
+ |
+The corresponding PNaCl records are: |
+ |
+.. naclcode:: |
+ |
+ 3: <0, 0, 1> |
+ 3: <1, 3> |
+ 3: <3, 4, 5, 6, 7> |
+ 3: <4, 1> |
+ 3: <3, 99, 66, 22, 12> |
+ |
+Valuesymtab Block |
+================= |
+ |
+TODO(kschimpf) |
+ |
+ |
+The *valuesymtab block* [ref] does not define any values. Rather, its only goal |
+is to associate text names with previously defined global addresses |
+(i.e. function, constant, and variable). Each association is defined by a |
+record in the valuesymtab block. Currently, only *intrinsic* [ref] function |
+addresses need a name. All other entries in this block are considered as a hint |
+for debugging. The PNaCl translator may (or may not) pass these names to the |
+running executable, allowing the (runtime) debugger to associate names with |
+addresses. |
+ |
+ |
+Module Block |
+============ |
+ |
+The module block, like all blocks, is enclosed in a pair of enter/exit records, |
+using block ID 8. A well-formed module block consists of the following records |
+(in order): |
+ |
+A version record |
+ The version record communicates which version of the PNaCl bitcode |
+ reader/writer should be used. Note that this is different than the PNaCl |
+ bitcode (ABI) version. The PNaCl bitcode (ABI) version defines what is |
+ expected in records, and is defined in the header record of the bitcode |
+ file. The version record defines the version of the PNaCL bitcode |
Jim Stichnoth
2014/06/06 18:24:48
PNaCL --> PNaCl
Jim Stichnoth
2014/06/06 18:24:48
PNaCL --> PNaCl
Karl
2014/06/30 22:09:03
Done.
|
+ reader/writer to use to convert records into bit sequences. |
+ |
+Optional local abbreviations |
+ Defines a list of local abbreviations to use for records within the module |
+ block. |
+ |
+An abbreviations block |
+ The abbreviations block defines user-defined, global abbreviations that are |
+ used to convert PNaCl records to bit sequences in blocks following the |
+ abbreviations block. |
+ |
+A types block |
+ The types block defines the set of all types used in the program. |
+ |
+A non-empty sequence of function address records |
+ Each record defines a function address used by the program. Function |
+ addresses must either be external, or defined internally by the program. If |
+ they are defined by the program, there must be a function block (appearing |
+ later in the module) that defines the sequence of instructions for each |
+ defined function. |
+ |
+A globals block defining the global variables. |
+ This block defines the set of global variable (addresses) used by the |
+ program. In addition to the addresses, each global variable also defines how |
+ the corresponding global variable is initialized. |
+ |
+An optional value symbol table block. |
+ This block, if defined, provides textual names for function and global |
+ variable addresses (previously defined in the module). Note that only names |
+ for intrinsic functions must be provided [ref]. Any additional names are |
+ hints that may (or may not) be used by the PNaCl translator, and be available |
+ for debugging when executed. |
+ |
+A sequence of function blocks. |
+ Each function block defines the corresponding control flow graph for each |
+ defined function. The order of function blocks is used to associate them with |
+ function addresses. The order of the defined function blocks must follow the |
+ same order as the corresponding function addresses defined in the module |
+ block. |
+ |
+Descriptions of the abbreviations [ref], types [ref], global variables [ref], |
+value symbol table [ref], and function [ref] blocks are not provided here. See |
+the appropriate reference for more details. The following subsections describe |
+each of the records that can appear in a module block. |
+ |
+Version |
+------- |
+ |
+The version record defines the implementation of the PNaCl reader/writer to |
+use. That is, the implementation that converts PNaCl records to bit |
+sequences. Note that this is different than the PNaCl version of the bitcode |
+file (encoded in the header record of the bitcode file). The PNaCl version |
+defines the valid forms of PNaCl records. The version record is specific to the |
+PNaCl version, and may have different values for different PNaCl versions. |
+ |
+Note that currently, only PNaCl bitcode version 2, and version record value 1 is |
+defined. |
+ |
+**Syntax** |
+ |
+.. naclcode:: |
+ |
+ version N; <A> |
+ |
+**Record** |
+ |
+.. naclcode:: |
+ |
+ AA: <1, N> |
+ |
+**Semantics** |
+ |
+The version record defines which PNaCl reader/writer rules should be |
+followed. *N* is the version number. Currently *N* must be 1. Future versions of |
+PNaCl may define additional legal values. *A* is the (optional) abbreviation |
+index associated with the record. |
+ |
+**Constraints** |
+ |
+.. naclcode:: |
+ |
+ AA = AbbrevIndex(A) |
+ |
+*Examples* |
+ |
+.. naclcode:: |
+ |
+ version 1; |
+ |
+The corresponding record is: |
+ |
+.. naclcode:: |
+ |
+ 3: <1, 1> |
+ |
+Function Address |
+---------------- |
+ |
+A function address record defines a function address. Defining a function |
+address also implies a corresponding implementation. *Defined* function |
+addresses define implementations while *declared* function addresses do not. |
+ |
+The implementation of a *defined* function address is provided by a |
+corresponding function block, appearing later in the module block. The |
+association of defining function address with the corresponding function block |
+is based on position. The *Nth* defining function address record, in the module |
+block, has its implementation in the *Nth* function block of that module block. |
+ |
+**Syntax** |
+ |
+.. naclcode:: |
+ |
+ PN LN T0 @fN ( T1 , ... , TM ); <A> |
+ |
+**Record** |
+ |
+.. naclcode:: |
+ |
+ AA: <8, T, C, P, L> |
+ |
+**Semantics** |
+ |
+Defines the function address *@fN*. *PN* is the name that specifies |
+the prototype value *P* associated with the function. A function |
+address is defined only if *P==0*. Otherwise, it is only declared. |
+The type of the function is defined by function type *@tT*. *L* |
+is the linkage specification corresponding to name *LN*. *C* is the |
+calling convention used by the function. *A* is the |
+(optional) abbreviation associated with the record. |
+ |
+Note that the function signature must be defined by a function type in the types |
+block. Hence, the return value must either be a primitive type, type *void*, or |
+a vector type. Parameter types can be a primitive or vector type. For the |
+integral types, only i32 and i64 can be used for a return or parameter type. All |
+other integer types are not allowed. |
+ |
+Valid prototype names *PN*, and corresponding *P* values, are: |
+ |
+= ======= |
+P PN |
+= ======= |
+1 declare |
+0 define |
+= ======= |
+ |
+Valid linkage names *LN*, and corresponding *L* values, are: |
+ |
+= ======== |
+L LN |
+= ======== |
+3 internal |
+0 external |
+= ======== |
+ |
+Currently, only one calling convention *C* is supported: |
+ |
+= ==================== |
+C Calling Convention |
+= ==================== |
+0 C calling convention |
+= ==================== |
+ |
+**Constraint** |
+ |
+.. naclcode:: |
+ |
+ AA = AbbrevIndex(A) |
+ T = TypeID(TypeOf(T0 ( T1 , ... , TN ))) |
+ N = NumFuncAddresses |
+ |
+**Updates** |
+ |
+.. naclcode:: |
+ |
+ ++NumFuncAddresses; |
+ TypeOf(@fN) = TypeOf(TypeID(i32)); |
+ TypeOfFcn(@fN) = TypeOf(@tT); |
+ |
+ if PN == 0: |
+ DefiningFcnIDs += @FN; |
+ ++NumDefinedFunctionAddresses; |
+ |
+**Examples** |
+ |
+.. naclcode:: |
+ |
+ module { |
+ ... |
+ types { |
+ @t0 = void; |
+ @t1 = i32; |
+ @t3 = float; |
+ @t4 = void (i32, float); |
+ @t5 = i32 (); |
+ } |
+ ... |
+ declare external void @f0(i32, float); |
+ define internal i32 @f1(); |
+ |
+This defines function addresses *@f0* and *@f1*. Function address *@f0* is |
+defined externally while *@f1* has an implementation (defined by a corresponding |
+function block). The type signature of *@f0* is defined by type *@t4* while the |
+type signature of *@f1* is *@t5*. |
+ |
+The corresponding records for these two function addresses are: |
+ |
+.. naclcode:: |
+ |
+ 3: <8, 4, 0, 1, 0> |
+ 3: <8, 5, 0, 0, 1> |
+ |
+Constants Blocks |
+================ |
+ |
+TODO(kschimpf) |
+ |
+Function Blocks |
+=============== |
+ |
+A function block defines the implementation of a *defined* function address. The |
+function address it defines is based on the position of the corresponding |
+*defined* function address. The Nth *defined* function address always |
+corresponds to the Nth function block in the module block. |
+ |
+A function definition contains a list of basic blocks, forming the CFG (control |
+flow graph). Each basic block contains a list of instructions, and ends with a |
+*terminator* [ref] (e.g. branch) instruction. |
+ |
+Basic blocks are not represented by records. Rather, context is implicit. The |
+first basic block begins with the first instruction record in the function |
+block. Blocks boundaries are determined by *terminator* instructions. The |
+instruction that follows a temrinator instruction begins a new basic block. |
Jim Stichnoth
2014/06/06 18:24:48
terminator
Karl
2014/06/30 22:09:03
Done.
|
+ |
+The first basic block in a function is special in two ways: it is immediately |
+executed on entrance to the function, and it is not allowed to have predecessor |
+basic blocks (i.e. there can't be any branches to the entry block of a |
+function). Because the entry block has no predecessors, it also can't have any |
+*PHI instructions* [ref]. |
+ |
+The parameters are implied by the type of the corresponding function |
+address. One parameter is defined for each argument of the function type |
+signature. |
+ |
+The number of basic blocks is defined by the count record. Each terminator |
+instruction ends the current basic block, and the next instruction begins a new |
+basic block. Basic blocks are numbered by the order they appear (starting with |
+index 0). Basic block IDs have the form *%bN*, where *N* corresponds to the |
+position of the basic block within the function block. |
+ |
+Each instruction, within a function block, corresponds to a corresponding PNaCl |
+record. The layout of a function block is the (basic block) count record, |
+followed by a sequence of instruction records. |
+ |
+For readability, PNaClAsm introduces block IDs. These block IDs do not |
+correspond to PNaCl records, since basic block boundaries are defined |
+implicitly, after terminator instructions. They appear only for readability. |
+ |
+Operands are typically defined using an *absolute index* [ref]. This absolute |
+index implicitly encodes function addresses, global addresses, parameters, |
+constants, and instructions that generate values. The encoding takes advantage |
+of the implied ordering of these values in the bitcode file, defining a block of |
+indices for each kind of identifier. That is, Indices are ordered by putting |
Jim Stichnoth
2014/06/06 18:24:47
Indices --> indices
Karl
2014/06/30 22:09:04
Done.
|
+function identifier indices first, followed by global address identifiers, |
+followed by parameter identifiers, followed by constant identifiers, and lastly |
+instruction value identifiers. |
+ |
+Most operands of instructions are encoded using a relative index value, rather |
+than absolute. The is done because most instruction operands refer to values |
Jim Stichnoth
2014/06/06 18:24:49
The is done --> This is done
Karl
2014/06/30 22:09:04
Done.
|
+defined earlier in the (same) basic block. As a result, the relative distance |
+(back) from the next value defining instruction is frequently a small |
+number. Small numbers tend to require fewer bits when they are converted to bit |
+sequences. |
+ |
+The following subsections define records that can appear in a function block. |
+ |
+Function enter |
+-------------- |
+ |
+PNaClAsm defines a function enter block construct. The corresponding record is |
+simply an enter block record, with BlockID value 12. All context about the |
+defining address is implicit by the position of the function block, and the |
+corresponding defining function address. To improve readability, PNaClAsm |
+includes the function signature into the syntax rule. |
+ |
+**Syntax** |
+ |
+.. naclcode:: |
+ |
+ function TR @fN ( T0 %p0, ... , TM %pM) { <B> |
+ |
+**Record** |
+ |
+ 1: <65535, 12, B> |
+ |
+**Semantics** |
+ |
+*B* is the number of bits reserved for abbreviations in the block. See |
+enter block records [ref] for more details. |
+ |
+The value of *N* corresponds to the positional index of the corresponding |
+defining function address this block is associated with. *M* is the number of |
+defined parameters (minus one) in the function heading. |
+ |
+**Constraints** |
+ |
+.. naclcode:: |
+ |
+ N == NumFcnImpls |
+ @fN in DefiningFcnIDs |
+ TypeOfFcn(@fN) == TypeOf(TypeID(TR (T0, ... , TM))) |
+ |
+**Updates** |
+ |
+.. naclcode:: |
+ |
+ ++NumFcnImpls; |
+ EnclosingFcnID = @fN; |
+ NumBasicBlocks = 0; |
+ ExpectedBlocks = 0; |
+ NumParams = M; |
+ for I in [0..M]: |
+ TypeOf(%pI) = TypeOf(TypeID(TI)); |
+ |
+**Examples** |
+ |
+.. naclcode:: |
+ |
+ types { |
+ ... |
+ @t10 = void (i32, float); |
+ ... |
+ } |
+ ... |
+ define internal void @f12(i32, float); |
+ ... |
+ function void @f12(i32 %p0, float %p1) { |
+ ... |
+ } |
+ |
+defines the enter block record: |
+ |
+.. naclcode:: |
+ |
+ 1: <65535, 12, 2> |
+ |
+Count Record |
+------------ |
+ |
+The count record, within a function block, defines the number of basic blocks |
+used to define the function implementation. It should be the first record in the |
+function block. |
+ |
+**Syntax** |
+ |
+.. naclcode:: |
+ |
+ blocks: N; <A> |
+ %b0: |
+ |
+**Record** |
+ |
+.. naclcode:: |
+ |
+ AA: <1, N> |
+ |
+**Semantics** |
+ |
+The count record defines the number *N* of basic blocks in the implemented |
+function. *A* is the (optional) abbreviation associated with the record. |
+ |
+**Constraints** |
+ |
+.. naclcode:: |
+ |
+ AA = AbbrevIndex(A) |
+ ExpectedBasicBlocks = 0 |
+ NumBasicBlocks = 0 |
+ |
+**Updates** |
+ |
+.. naclcode:: |
+ |
+ ExpectedBlocks = N; |
+ |
+**Examples** |
+ |
+.. naclcode:: |
+ |
+ blocks: 5 |
+ |
+The corresponding PNaCl bitcode record is: |
+ |
+.. naclcode:: |
+ |
+ 3: <1, 5> |
+ |
+Terminator Instructions |
+----------------------- |
+ |
+Terminator instructions are instructions that appear in a function block, and |
+define the end of the current basic block. A terminator instruction indicates |
+which block should be executed after the current block is finished. The function |
+block is well formed only if the number of terminator instructions, in the |
+function block, corresponds to the value defined by the corresponding count |
+block. |
+ |
+Return Void Instruction |
+^^^^^^^^^^^^^^^^^^^^^^^ |
+ |
+The return void instruction is used to return control from a function back to |
+the caller, without returning any value. |
+ |
+**Syntax** |
+ |
+.. naclcode:: |
+ |
+ ret; <A> |
+ %bB: |
+ |
+**Record** |
+ |
+.. naclcode:: |
+ |
+ AA: <10> |
+ |
+**Semantics** |
+ |
+The return instruction returns control to the calling function. |
+ |
+*B* is the number associated with the next basic block. Label *%bB:* only |
+appears if *B < ExpectedBasicBlocks*. That is, the label is omitted only if this |
+terminator instruction is the last instruction in the function block. *A* is |
+the (optional) abbreviation index associated with the record. |
+ |
+**Constraints** |
+ |
+.. naclcode:: |
+ |
+ AA = AbbrevIndex(A) |
+ B == NumBasicBlocks + 1 |
+ NumBasicBlocks < ExpectedBasicBLocks |
+ ReturnType(TypeOf(EnclosingFcnID)) == void |
+ |
+**Updates** |
+ |
+.. naclcode:: |
+ |
+ ++NumBasicBlocks; |
+ |
+**Examples** |
+ |
+The following shows the implementation of a function that simply returns. |
+ |
+.. naclcode:: |
+ |
+ function void @f5() { |
+ blocks: 1; |
+ %b0: |
+ ret; |
+ } |
+ |
+The corresponding PNaCl records are: |
+ |
+.. naclcode:: |
+ |
+ 1: <65535, 12, 2> |
+ 3: <1, 1> |
+ 3: <10> |
+ 0: <65534> |
+ |
+Return Value Instruction |
+^^^^^^^^^^^^^^^^^^^^^^^^ |
+ |
+The return value instruction is used to return control from a function back to |
+the caller, including a value. The value must correspond to the return type of |
+the enclosing function. |
+ |
+**Syntax** |
+ |
+.. naclcode:: |
+ |
+ ret T V; <A> |
+ %bB: |
+ |
+**Record** |
+ |
+.. naclcode:: |
+ |
+ AA: <10, VV> |
+ |
+**Semantics** |
+ |
+The return value instruction returns control to the calling function, returning |
+the provided value. |
+ |
+*V* is the value to return. Type *T* must be of the type returned by the |
+function. It must also be the type associated with value *V*. *A* is the |
+(optional) abbreviation index associated with the record. |
+ |
+*B* is the number associated with the next basic block. Label *%bB:* only |
+appears if *B < ExpectedBasicBlocks*. That is, the label is omitted only if this |
+terminator instruction is the last instruction in the function block. |
+ |
+The return type *T* must either be a primitive type, or a vector type. If the |
+return type is an integral type, it must be either i32 or i64. |
+ |
+**Constraints** |
+ |
+.. naclcode:: |
+ |
+ AA = AbbrevIndex(A) |
+ VV = RelativeIndex(V) |
+ B = NumBasicBlocks + 1 |
+ NumBasicBlocks < ExpectedBasicBlocks |
+ T = TypeOf(V) = ReturnType(TypeOf(EnclosingFcnID)) |
+ |
+**Updates** |
+ |
+.. naclcode:: |
+ |
+ ++NumBasicBlocks; |
+ |
+**Examples** |
+ |
+The following shows a return statement that returns the value generated by the |
+previous instruction: |
+ |
+.. naclcode:: |
+ |
+ function i32 @f5(i32 %p0) { |
+ blocks: 1; |
+ @b0: |
+ ret i32 @p0; |
+ } |
+ |
+The corresponding records are: |
+ |
+.. naclcode:: |
+ |
+ 1: <65535, 12, 2> |
+ 3: <1, 1> |
+ 3: <10, 1> |
+ 0: <65534> |
+ |
+Unconditional Branch Instruction |
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
+ |
+The unconditional branch instruction is used to cause control flow to transfer |
+to a different basic block of the function. |
+ |
+**Syntax** |
+ |
+.. naclcode:: |
+ |
+ br %bN; <A> |
+ %bB: |
+ |
+**Record** |
+ |
+.. naclcode:: |
+ |
+ AA: <11, N> |
+ |
+**Semantics** |
+ |
+The unconditional branch instruction causes control flow to transfer to basic |
+block *N*. *A* is the (optional) abbreviation index associated with the record. |
+ |
+*B* is the number associated with the next basic block. Label *%bB:* only |
+appears if *B < ExpectedBasicBlocks*. That is, the label is omitted only if this |
+terminator instruction is the last instruction in the function block. |
+ |
+**Constraints** |
+ |
+.. naclcode:: |
+ |
+ AA = AbbrevIndex(A) |
+ 0 < N |
+ N < ExpectedBasicBlocks |
+ B = NumBasicBlocks + 1 |
+ NumBasicBlocks < ExpectedBasicBlocks |
+ |
+**Updates** |
+ |
+.. naclcode:: |
+ |
+ ++NumBasicBlocks; |
+ |
+**Examples** |
+ |
+.. naclcode:: |
+ |
+ br %b2; |
+ |
+This branch instruction branches to the 3rd basic block of the function. It |
+defines the following PNaCl record: |
+ |
+.. naclcode:: |
+ |
+ 3: <11, 2> |
+ |
+Conditional Branch Instruction |
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
+ |
+The conditional branch instruction is used to cause control flow to transfer to |
+a different basic block of the function, based on a boolean test condition. |
+ |
+**Syntax** |
+ |
+.. naclcode:: |
+ |
+ br i1 C, %bT, %bBF; <A> |
+ %bB: |
+ |
+**Record** |
+ |
+.. naclcode:: |
+ |
+ AA: <11, T, F, V> |
+ |
+**Semantics** |
+ |
+Upon execution of a conditional branch instruction, the *i1* (boolean) argument |
+*C* is evaluated. If the value is *true*, control flows to basic block |
+*%bT*. Otherwise control flows to basic block *%bF*. *A* is the (optional) |
+abbreviation index associated with the record. |
+ |
+*B* is the number associated with the next basic block. Label *%bB:* only |
+appears if *B < ExpectedBasicBlocks*. That is, the label is omitted only if this |
+terminator instruction is the last instruction in the function block. |
+ |
+**Constraints** |
+ |
+.. naclcode:: |
+ |
+ AA = AbbrevIndex(A) |
+ V = RelativeIndex(C) |
+ 0 < T |
+ B1 < ExpectedBasicBlocks |
+ 0 < F |
+ B2 < ExpectedBasicBlocks |
+ B = NumBasicBlocks + 1 |
+ NumBasicBlocks < ExpectedBasicBlocks |
+ TypeOf(C) == i1 |
+ |
+**Updates** |
+ |
+.. naclcode:: |
+ |
+ ++NumBasicBlocks; |
+ |
+**Examples** |
+ |
+.. naclcode:: |
+ |
+ function i32 @f2(i32 %p0, i32 %p1) { |
+ blocks: 3; |
+ %b0: |
+ %v0 = cmp eq i32 %p0, %p1; |
+ br i1 %v0, %b1, %b2; |
+ %b1: |
+ ret i32 %p0; |
+ %b2: |
+ ret i32 %p1; |
+ |
+The corresponding records are: |
+ |
+.. naclcode:: |
+ |
+ 1: <65535, 12, 2> |
+ 3: <1, 3> |
+ 3: <28, 2, 1, 32> |
+ 3: <11, 2, 1, 1> |
+ 3: <10, 3> |
+ 3: <10, 2> |
+ 0: <65534> |
+ |
+Unreachable |
+^^^^^^^^^^^ |
+ |
+The unreachable instruction has no defined semantics. The instruction is used to |
+inform the *PNaCl translator* that control can't reach this instruction. |
+ |
+**Syntax** |
+ |
+.. naclcode:: |
+ |
+ unreachable; <A> |
+ %bB: |
+ |
+**Record** |
+ |
+.. naclcode:: |
+ |
+ AA: <15> |
+ |
+**Semantics** |
+ |
+Directive to the *PNaCl translator* that this instruction is unreachable. *A* |
+is the (optional) abbreviation index associated with the record. |
+ |
+*B* is the number associated with the next basic block. Label *%bB:* only |
+appears if *B < ExpectedBasicBlocks*. That is, the label is omitted only if this |
+terminator instruction is the last instruction in the function block. |
+ |
+**Constraints** |
+ |
+.. naclcode:: |
+ |
+ AA = AbbrevIndex(A) |
+ B = NumBasicBlocks + 1 |
+ NumBasicBlocks < ExpectedBasicBlocks |
+ |
+**Updates** |
+ |
+.. naclcode:: |
+ |
+ ++NumBasicBlocks; |
+ |
+**Examples** |
+ |
+TODO(kschimpf) |
+ |
+Switch Instruction |
+^^^^^^^^^^^^^^^^^^ |
+ |
+TODO(kschimpf) |
+ |
+Integer Binary Instructions |
+----------------------------- |
+ |
+Binary instructions are used to do most of the computation in a program. This |
+section focusses on binary instructions that operator on integral values, or |
Jim Stichnoth
2014/06/06 18:24:49
focusses --> focuses
jvoung (off chromium)
2014/06/06 20:09:15
focuses
|
+vectors of integral values. |
+ |
+All binary operations require two operands of the same type, execute an |
+operation on them, and produce a value. The value may represent multiple values |
+if the type is a vector type. The result value always has the same type as its |
+operands. |
+ |
+Some integer binary operations can be applied to both signed and unsigned |
+integers. Others, the sign is significant. In general, if the sign plays a role |
+in the instruction, the sign information is encoded into the name of the |
+instruction. |
+ |
+For most binary operations (except some of the logical operations), integral |
+type i1 is disallowed. |
+ |
+Integer Add |
+^^^^^^^^^^^ |
+ |
+The integer add instruction returns the sum of its two arguments. Both arguments |
+and the result must be of the same type. That type must be integral, or an |
+integral vector type. |
+ |
+**Syntax** |
+ |
+.. naclcode:: |
+ |
+ %vN = add T V1, V2; <A> |
+ |
+**Record** |
+ |
+ AA: <2, VV1, VV2, 0> |
+ |
+**Semantics** |
+ |
+The integer add instruction returns the sum of its two arguments. Arguments *V1* and |
Jim Stichnoth
2014/06/06 18:24:47
80-col
Karl
2014/06/30 22:09:05
Done.
|
+*V2*, and the result *%vN*, must be of type *T*. *T* must be an integral type, |
+or an integral vector type. *N* is defined by the record position, defining the |
+corresponding value generated by the instruction. *A* is the (optional) |
+abbreviation associated with the corresponding record. |
+ |
+Overflow conditions are ignored, and the result returned is the mathematical |
jvoung (off chromium)
2014/06/06 20:09:15
"Overflow conditions are ignored, and ..."
Is "ig
Karl
2014/06/30 22:09:04
Done.
|
+result modulo *exp(2,n)*, where *n* is the bitwidth of the integer result. |
+ |
+Because integers are assumed to use a two's complement representation, |
+this instruction is appropriate for both signed and unsigned integers. |
+ |
+In the add instruction, Integral type i1 (and vectors on integral type i1) is |
Jim Stichnoth
2014/06/06 18:24:49
Integral --> integral
Karl
2014/06/30 22:09:05
Done.
|
+disallowed. |
+ |
+**Constraints** |
+ |
+.. naclcode:: |
+ |
+ AA = AbbrevIndex(A) |
+ VV1 = RelativeIndex(V1) |
+ VV2 = RelativeIndex(V2) |
+ T = TypeOf(V1) = TypeOf(V2) |
+ IsInteger(UnderlyingType(T)) |
+ UnderlyingType(T) != i1 |
+ N = NumValuedInsts |
+ NumBasicBlocks < ExpectedBasicBlocks |
+ |
+**Updates** |
+ |
+.. naclcode:: |
+ |
+ ++NumValuedInsts; |
+ TypeOf(%vN) = T |
+ |
+**Examples** |
+ |
+.. naclcode:: |
+ |
+ function i32 @f0(i32 %p0, i32 %p1) { |
+ blocks: 1; |
+ %b0: |
+ %v0 = add i32 %p0, %p1; |
+ %v1 = add i32 %p0, %v0; |
+ ret i32 %v1; |
+ } |
+ |
+The corresponding records are: |
+ |
+.. naclcode:: |
+ |
+ 1: <65535, 12, 2> |
+ 3: <1, 1> |
+ 3: <2, 2, 1, 0> |
+ 3: <2, 3, 1, 0> |
+ 3: <10, 1> |
+ 0: <65534> |
+ |
+Integer Subtract |
+^^^^^^^^^^^^^^^^ |
+ |
+The integer subtract instruction returns the difference of its two arguments. |
+Both arguments and the result must be of the same type. That type must be |
+integral, or an integral vector type. |
+ |
+Note: Since there isn't a negate instruction, subtraction from constant zero |
+should be used to negate values. |
+ |
+**Syntax** |
+ |
+.. naclcode:: |
+ |
+ %vN = sub T V1, V2; <A> |
+ |
+**Record** |
+ |
+.. naclcode:: |
+ |
+ AA: <2, VV1, VV2, 1> |
+ |
+**Semantics** |
+ |
+The integer subtract returns the difference of its two arguments. Arguments *V1* |
+and *V2*, and the result *%vN* must be of type *T*. *T* must be an integral |
+type, or an integral vector type. *N* is defined by the record position, defining |
Jim Stichnoth
2014/06/06 18:24:49
80-col
|
+the corresponding value generated by the instruction. *A* is the (optional) |
+abbreviation ¯associated with the corresponding record. |
+ |
+Underflow conditions are ignored, and the result returned is the mathematical |
+result modulo *exp(2, n)*, where *n* is the integer bitwidth of the result. |
+ |
+Because integers are assumed to use a two's complement representation, |
+this instruction is appropriate for both signed and unsigned integers. |
+ |
+In the subtract instruction, Integral type i1 is disallowed. |
Jim Stichnoth
2014/06/06 18:24:48
Integral --> integral
|
+ |
+**Constraints** |
+ |
+.. naclcode:: |
+ |
+ AA == AbbrevIndex(A) |
+ VV1 == RelativeIndex(V1) |
+ VV2 == RelativeIndex(V2) |
+ T == TypeOf(V1) == TypeOf(V2) |
+ IsInteger(UnderlyingType(T)) |
+ UnderlyingType(T) != i1 |
+ N == NumValuedInsts |
+ NumBasicBlocks < ExpectedBasicBlocks |
+ |
+**Updates** |
+ |
+.. naclcode:: |
+ |
+ ++NumValuedInsts; |
+ TypeOf(%vN) = T |
+ |
+**Examples** |
+ |
+.. naclcode:: |
+ |
+ function i32 @f0(i32 %p0, i32 %p1) { |
+ blocks: 1; |
+ %b0: |
+ %v0 = sub i32 %p0, %p1; |
+ %v1 = sub i32 %p0, %v0; |
+ ret i32 %v1; |
+ } |
+ |
+The corresponding records are: |
+ |
+.. naclcode:: |
+ |
+ 1: <65535, 12, 2> |
+ 3: <1, 1> |
+ 3: <2, 2, 1, 1> |
+ 3: <2, 3, 1, 1> |
+ 3: <10, 1> |
+ 0: <65534> |
+ |
+Integer Multiply |
+^^^^^^^^^^^^^^^^ |
+ |
+The integer multiply instruction returns the product of its two arguments. Both |
+arguments and the result must be of the same type. That type must be integral, |
+or an integral based vector type. |
+ |
+**Syntax** |
+ |
+.. naclcode:: |
+ |
+ &vN = mul T V1, V2; <A> |
+ |
+**Record** |
+ |
+.. naclcode:: |
+ |
+ AA: <2, VV1, VV2, 2> |
+ |
+**Semantics** |
+ |
+The intebger multiply instruction returns the product of its two |
Jim Stichnoth
2014/06/06 18:24:46
integer
Karl
2014/06/30 22:09:05
Done.
|
+arguments. Arguments *V1* and *V2*, and the result *%vN*, must be of type *T*. |
+*T* must be an integral type, or an integral vector type. *N* is defined by the |
+record position, defining the corresponding value generated by the |
+instruction. *A* is the (optional) abbreviation associated with the |
+corresponding record. |
+ |
+Overflow conditions are ignored, and the result returned is the mathematical |
+result modulo *exp(2, n)*, where *n* is the bitwidth of the result. |
+ |
+Because integers are assumed to use a two's complement representation, |
+this instruction is appropriate for both signed and unsigned integers. |
+ |
+In the subtract instruction, Integral type i1 is disallowed. |
Jim Stichnoth
2014/06/06 18:24:47
Integral --> integral
Karl
2014/06/30 22:09:05
Done.
|
+ |
+**Constraints** |
+ |
+.. naclcode:: |
+ |
+ AA == AbbrevIndex(A) |
+ VV1 == RelativeIndex(V1) |
+ VV2 == RelativeIndex(V2) |
+ T == TypeOf(V1) == TypeOf(V2) |
+ IsInteger(UnderlyingType(T)) |
+ UnderlyingType(T) != i1 |
+ N == NumValuedInsts |
+ NumBasicBlocks < ExpectedBasicBlocks |
+ |
+**Updates** |
+ |
+.. naclcode:: |
+ |
+ ++NumValuedInsts; |
+ TypeOf(%vN) = T |
+ |
+**Examples** |
+ |
+.. naclcode:: |
+ |
+ function i32 @f0(i32 %p0, i32 %p1) { |
+ blocks: 1; |
+ %b0: |
+ %v0 = mul i32 %p0, %p1; |
+ %v1 = mul i32 %v0, %p1; |
+ ret i32 %v1; |
+ } |
+ |
+The corresponding records are: |
+ |
+.. naclcode:: |
+ |
+ 1: <65535, 12, 2> |
+ 3: <1, 1> |
+ 3: <2, 2, 1, 2> |
+ 3: <2, 1, 2, 2> |
+ 3: <10, 1> |
+ 0: <65534> |
+ |
+Signed Integer Divide |
+^^^^^^^^^^^^^^^^^^^^^ |
+ |
+The signed integer divide instruction returns the quotient of its two arguments. |
+Both arguments and the result must be of the same type. That type must be |
+integral, or an integral vector type. |
+ |
+**Syntax** |
+ |
+.. naclcode:: |
+ |
+ %vN = sdiv T V1, V2; <A> |
+ |
+**Record** |
+ |
+.. naclcode:: |
+ |
+ AA: <2, VV1, VV2, 4> |
+ |
+**Semantics** |
+ |
+The divide instruction returns the quotient of its two arguments. Arguments *V1* |
+and *V2*, and the result *%vN*, must be of type *T*. *T* must be a integral |
+type, or an integral vector type. *N* is defined by the record position, |
+defining the corresponding value generated by the instruction. *A* is the |
+(optional) abbreviation associated with the corresponding record. |
+ |
+Signed values are assumed. Note that signed and unsigned integer division are |
+distinct operations. For unsigned integer division use the unsigned integer |
+divide instruction (udiv). |
+ |
+In the signed integer divide instruction, integral type i1 is |
+disallowed. Integer division by zero is guaranteed to trap. Overflow is also |
+undefined. |
jvoung (off chromium)
2014/06/06 20:09:14
Maybe keep the clarification that overflow happens
Karl
2014/06/30 22:09:03
While I agree we should consider tightening this,
|
+ |
+**Constraints** |
+ |
+.. naclcode:: |
+ |
+ AA == AbbrevIndex(A) |
+ VV1 == RelativeIndex(V1) |
+ VV2 == RelativeIndex(V2) |
+ T == TypeOf(V1) == TypeOf(V2) |
+ IsInteger(UnderlyingType(T)) |
+ UnderlyingType(T) != i1 |
+ N == NumValuedInsts |
+ NumBasicBlocks < ExpectedBasicBlocks |
+ |
+**Updates** |
+ |
+.. naclcode:: |
+ |
+ ++NumValuedInsts; |
+ TypeOf(%vN) = T |
+ |
+**Examples** |
+ |
+.. naclcode:: |
+ |
+ function i32 @f0(i32 %p0, i32 %p1) { |
+ blocks: 1; |
+ %b0: |
+ %v0 = sdiv i32 %p0, %p1; |
+ %v1 = sdiv i32 %v0, %p1; |
+ ret i32 %v1; |
+ } |
+ |
+The corresponding records are: |
+ |
+.. naclcode:: |
+ |
+ 1: <65535, 12, 2> |
+ 3: <1, 1> |
+ 3: <2, 2, 1, 4> |
+ 3: <2, 1, 2, 4> |
+ 3: <10, 1> |
+ 0: <65534> |
+ |
+Unsigned Integer Divide |
+^^^^^^^^^^^^^^^^^^^^^^^ |
+ |
+The unsigned integer divide instruction returns the quotient of its two |
+arguments. Both the arguments and the result must be of the same type. That type |
+must be integral, or an integral vector type. |
+ |
+**Syntax** |
+ |
+.. naclcode:: |
+ |
+ %vN = udiv T V1, V2; <a> |
+ |
+**Record** |
+ |
+.. naclcode:: |
+ |
+ AA: <2, A1, A2, 3> |
+ |
+**Semantics** |
+ |
+The unsigned integer divide instruction returns the quotient of its two |
+arguments. Arguments *V1* and *V2*, and the result *%vN*, must be of type |
+*T*. *T* must be an integral type, or an integral vector type. *N* is defined |
+by the record position, defining the corresponding value generated by the |
+instruction. *A* is the (optional) abbreviation associated with the |
+corresponding record. |
+ |
+Unsigned integral values are assumed. Note that signed and unsigned integer |
+division are distinct operations. For signed integer division use the signed |
+integer divide instruction (sdiv). |
+ |
+In the unsigned integer divide instruction, Integral type i1 is |
Jim Stichnoth
2014/06/06 18:24:46
Integral --> integral
Karl
2014/06/30 22:09:05
Done.
|
+disallowed. Division by zero is guaranteed to trap. Overflow is also undefined. |
jvoung (off chromium)
2014/06/06 20:09:14
When would overflow happen, if these are unsigned?
Karl
2014/06/30 22:09:03
Removing sentence.
|
+ |
+**Constraints** |
+ |
+.. naclcode:: |
+ |
+ AA == AbbrevIndex(A) |
+ VV1 == RelativeIndex(V1) |
+ VV2 == RelativeIndex(V2) |
+ T == TypeOf(V1) == TypeOf(V2) |
+ IsInteger(UnderlyingType(T)) |
+ UnderlyingType(T) != i1 |
+ N == NumValuedInsts |
+ NumBasicBlocks < ExpectedBasicBlocks |
+ |
+**Updates** |
+ |
+.. naclcode:: |
+ |
+ ++NumValuedInsts; |
+ TypeOf(%vN) = T |
+ |
+**Examples** |
+ |
+.. naclcode:: |
+ |
+ function i32 @f0(i32 %p0, i32 %p1) { |
+ blocks: 1; |
+ %b0: |
+ %v0 = udiv i32 %p0, %p1; |
+ %v1 = udiv i32 %v0, %p1; |
+ ret i32 %v1; |
+ } |
+ |
+The corresponding records are: |
+ |
+.. naclcode:: |
+ |
+ 1: <65535, 12, 2> |
+ 3: <1, 1> |
+ 3: <2, 2, 1, 3> |
+ 3: <2, 1, 2, 3> |
+ 3: <10, 1> |
+ 0: <65534> |
+ |
+Signed Integer Remainder |
+^^^^^^^^^^^^^^^^^^^^^^^^ |
+ |
+The signed integer remainder instruction returns the remainder of the quotient |
+of its two arguments. Both arguments and the result must be of the same |
+type. That type must be integral, or an integral based vector type. |
+ |
+**Syntax** |
+ |
+.. naclcode:: |
+ |
+ %vN = srem T V1, V2; <A> |
+ |
+**Record** |
+ |
+.. naclcode:: |
+ |
+ AA: <2, VV1, VV2, 6> |
+ |
+**Semantics** |
+ |
+The signed integer remainder instruction returns the remainder of the quotient |
+of its two arguments. Arguments *V1* and *V2*, and the result *%vN*, must be of |
+type *T*. *T* must be a integral type, or an integral vector type. *N* is |
+defined by the record position, defining the corresponding value generated by |
+the instruction. *A* is the (optional) abbreviation associated with the |
+corresponding record. |
+ |
+Signed values are assumed. Note that signed and unsigned integer division are |
+distinct operations. For unsigned integer division use the unsigned integer |
+remainder instruction (urem). |
+ |
+In the signed integer remainder instruction, Integral type i1 is disallowed. |
Jim Stichnoth
2014/06/06 18:24:47
Integral --> integral
|
+Division by zero is guaranteed to trap. Overflow is also undefined. |
+ |
+**Constraints** |
+ |
+.. naclcode:: |
+ |
+ AA == AbbrevIndex(A) |
+ VV1 == RelativeIndex(V1) |
+ VV2 == RelativeIndex(V2) |
+ T == TypeOf(V1) == TypeOf(V2) |
+ IsInteger(UnderlyingType(T)) |
+ UnderlyingType(T) != i1 |
+ N == NumValuedInsts |
+ NumBasicBlocks < ExpectedBasicBlocks |
+ |
+**Updates** |
+ |
+.. naclcode:: |
+ |
+ ++NumValuedInsts; |
+ TypeOf(%vN) = T |
+ |
+**Examples** |
+ |
+.. naclcode:: |
+ |
+ function i32 @f0(i32 %p0, i32 %p1) { |
+ blocks: 1; |
+ %b0: |
+ %v0 = srem i32 %p0, %p1; |
+ %v1 = srem i32 %v0, %p1; |
+ ret i32 %v1; |
+ } |
+ |
+The corresponding records are: |
+ |
+.. naclcode:: |
+ |
+ 1: <65535, 12, 2> |
+ 3: <1, 1> |
+ 3: <2, 2, 1, 6> |
+ 3: <2, 1, 2, 6> |
+ 3: <10, 1> |
+ 0: <65534> |
+ |
+Unsigned Integer Remainder Instruction |
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
+ |
+The unsigned integer remainder instruction returns the remainder of the quotient |
+of its two arguments. Both the arguments and the result must be of the same |
+type. The type must be integral, or an integral vector type. |
+ |
+**Syntax** |
+ |
+.. naclcode:: |
+ |
+ %vN = urem T V1, V2; <A> |
+ |
+**Record** |
+ |
+.. naclcode:: |
+ |
+ AA: <2, A1, A2, 5> |
+ |
+**Semantics** |
+ |
+The unsigned integer remainder instruction returns the remainder of the quotient |
+of its two arguments. Arguments *V1* and *V2*, and the result *%vN*, must be of |
+type *T*. *T* must be an integral type, or an integral vector type. *N* is |
+defined by the record position, defining the corresponding value generated by |
+the instruction. *A* is the (optional) abbreviation associated with the |
+corresponding record. |
+ |
+Unsigned values are assumed. Note that signed and unsigned integer division are |
+distinct operations. For signed integer division use the remainder instruction |
+(srem). |
+ |
+In the unsigned integer remainder instruction, Integral type i1 is disallowed. |
Jim Stichnoth
2014/06/06 18:24:46
Integral --> integral
|
+Division by zero is guaranteed to trap. Overflow is also undefined. |
jvoung (off chromium)
2014/06/06 20:09:14
similar, overflow?
Karl
2014/06/30 22:09:03
Done.
|
+ |
+**Constraints** |
+ |
+.. naclcode:: |
+ |
+ AA == AbbrevIndex(A) |
+ VV1 == RelativeIndex(V1) |
+ VV2 == RelativeIndex(V2) |
+ T == TypeOf(V1) == TypeOf(V2) |
+ IsInteger(UnderlyingType(T)) |
+ UnderlyingType(T) != i1 |
+ N == NumValuedInsts |
+ NumBasicBlocks < ExpectedBasicBlocks |
+ |
+**Updates** |
+ |
+.. naclcode:: |
+ |
+ ++NumValuedInsts; |
+ TypeOf(%vN) = T |
+ |
+**Examples** |
+ |
+.. naclcode:: |
+ |
+ function i32 @f0(i32 %p0, i32 %p1) { |
+ blocks: 1; |
+ %b0: |
+ %v0 = srem i32 %p0, %p1; |
+ %v1 = srem i32 %v0, %p1; |
+ ret i32 %v1; |
+ } |
+ |
+The corresponding records are: |
+ |
+.. naclcode:: |
+ |
+ 1: <65535, 12, 2> |
+ 3: <1, 1> |
+ 3: <2, 2, 1, 5> |
+ 3: <2, 1, 2, 5> |
+ 3: <10, 1> |
+ 0: <65534> |
+ |
+Shift Left |
+^^^^^^^^^^ |
+ |
+The (integer) shift left instruction returns the first operand, shifted to the |
+left a specified number of bits with zero fill. The shifted value must be |
+integral, or an integral vector type. |
+ |
+**Syntax** |
+ |
+.. naclcode:: |
+ |
+ %vN = shl T V1, V2; <A> |
+ |
+**Record** |
+ |
+.. naclcode:: |
+ |
+ AA: <2, VV1, VV2, 7> |
+ |
+**Semantics** |
+ |
+This instruction performs a shift left operation. Argument *V1* and the result |
+*%vN* must be of type *T*. *T* nust be an integral, or a vector of |
+integrals. *V2* must be an integral type. *N* is defined by the record position, |
+defining the corresponding value generated by the instruction. *A* is the |
+(optional) abbreviation associated with the corresponding record. |
+ |
+*V2* is assumed to be unsigned. The least significant bits of the result will |
+be filled with zero bits after the shift. If *V2* is (statically or dynamically) |
+is negative or equal to or larger than the number of bits in *V1*, the result is |
+undefined. If the arguments are vectors, each vector element of *V1* is shifted |
+by the corresponding shift amount in *V2*. |
+ |
+In the shift left instruction, Integral type i1 is disallowed for either |
Jim Stichnoth
2014/06/06 18:24:50
Integral --> integral
|
+argument. |
+ |
+**Constraints** |
+ |
+.. naclcode:: |
+ |
+ AA == AbbrevIndex(A) |
+ VV1 == RelativeIndex(V1) |
+ VV2 == RelativeIndex(V2) |
+ T == TypeOf(V1) |
+ IsInteger(TypeOf(V2)) |
+ IsInteger(UnderlyingType(T)) |
+ UnderlyingType(T) != i1 |
+ UnderlyingType(TypeOf(V2)) != i1 |
+ N == NumValuedInsts |
+ NumBasicBlocks < ExpectedBasicBlocks |
+ |
+**Updates** |
+ |
+.. naclcode:: |
+ |
+ ++NumValuedInsts; |
+ TypeOf(%vN) = T |
+ |
+**Examples** |
+ |
+.. naclcode:: |
+ |
+ function i32 @f0(i32 %p0, i32 %p1) { |
+ blocks: 1; |
+ %b0: |
+ %v0 = shl i32 %p0, %p1; |
+ %v1 = shl i32 %v0, %p1; |
+ ret i32 %v1; |
+ } |
+ |
+The corresponding records are: |
+ |
+.. naclcode:: |
+ |
+ 1: <65535, 12, 2> |
+ 3: <1, 1> |
+ 3: <2, 2, 1, 7> |
+ 3: <2, 1, 2, 7> |
+ 3: <10, 1> |
+ 0: <65534> |
+ |
+Logical Shift Right |
+^^^^^^^^^^^^^^^^^^^ |
+ |
+The logical shift right instruction returns the first operand, shifted |
+to the right a specified number of bits with zero fill. |
+ |
+**Syntax** |
+ |
+.. naclcode:: |
+ |
+ %vN = lshr T V1, V2; <A> |
+ |
+**Record** |
+ |
+.. naclcode:: |
+ |
+ AA: <2, VV1, VV2, 8> |
+ |
+**Semantics** |
+ |
+This instruction performs a logical shift right operation. Arguments *V1* and |
+the result *%vN* must be of type *T*. *T* nust be an integral, or a vector of |
+integrals. *V2* must be an integral type. *N* is defined by the record position, |
+defining the corresponding value generated by the instruction. *A* is the |
+(optional) abbreviation associated with the corresponding record. |
+ |
+*V2* is assumed to be unsigned. The most significant bits of the result will be |
+filled with zero bits after the shift. If *V2* is (statically or dynamically) |
+negative or equal to or larger than the number of bits in *V1*, the result is |
+undefined. If the arguments are vectors, each vector element of *V1* is shifted |
+by the corresponding shift amount in *V2*. |
+ |
+In the logical shift right instruction, Integral type i1 is disallowed for |
Jim Stichnoth
2014/06/06 18:24:49
Integral --> integral
|
+either argument. |
+ |
+**Constraints** |
+ |
+.. naclcode:: |
+ |
+ AA = AbbrevIndex(A) |
+ VV1 == RelativeIndex(V1) |
+ VV2 == RelativeIndex(V2) |
+ T == TypeOf(V1) |
+ IsInteger(TypeOf(V2)) |
+ IsInteger(UnderlyingType(T)) |
+ UnderlyingType(T) != i1 |
+ UnderlyingType(TypeOf(V2)) != i1 |
+ N == NumValuedInsts |
+ NumBasicBlocks < ExpectedBasicBlocks |
+ |
+**Updates** |
+ |
+.. naclcode:: |
+ |
+ ++NumValuedInsts; |
+ TypeOf(%vN) = T |
+ |
+**Examples** |
+ |
+.. naclcode:: |
+ |
+ function i32 @f0(i32 %p0, i32 %p1) { |
+ blocks: 1; |
+ %b0: |
+ %v0 = lshr i32 %p0, %p1; |
+ %v1 = lshr i32 %v0, %p1; |
+ ret i32 %v1; |
+ } |
+ |
+The corresponding records are: |
+ |
+.. naclcode:: |
+ |
+ 1: <65535, 12, 2> |
+ 3: <1, 1> |
+ 3: <2, 2, 1, 8> |
+ 3: <2, 1, 2, 8> |
+ 3: <10, 1> |
+ 0: <65534> |
+ |
+Arithmetic Shift Right |
+^^^^^^^^^^^^^^^^^^^^^^ |
+ |
+The arithmetic shift right instruction returns the first operand, |
+shifted to the right a specified number of bits with sign extension. |
+ |
+**Syntax** |
+ |
+.. naclcode:: |
+ |
+ %vN = ashr T V1, V2; <A> |
+ |
+**Record** |
+ |
+.. naclcode:: |
+ |
+ AA: <2, VV1, VVA2, 9> |
+ |
+**Semantics** |
+ |
+This instruction performs an arithmetic shift right operation. Arguments *V1* |
+and the result *%vN* must be of type *T*. *T* nust be an integral, or a vector |
+of integrals. *V2* must be an integral type. *N* is defined by the record |
+position, defining the corresponding value generated by the instruction. *A* is |
+the (optional) abbreviation associated with the corresponding record. |
+ |
+*V2* is assumed to be unsigned. The most significant bits of the result will be |
+filled with the sign bit of *V1*. If *V2* is (statically or dynamically) |
+negative or equal to or larger than the number of bits in *V1*, the result is |
+undefined. If the arguments are vectors, each vector element of *V1* is shifted |
+by the corresponding shift amount in *V2*. |
+ |
+In the arithmetic shift right instruction, integral type i1 is disallowed for |
+either argument. |
+ |
+**Constraints** |
+ |
+.. naclcode:: |
+ |
+ AA == AbbrevIndex(A) |
+ VV1 == RelativeIndex(V1) |
+ VV2 == RelativeIndex(V2) |
+ T == TypeOf(V1) |
+ IsInteger(TypeOf(V2)) |
+ UnderlyingType(T) != i1 |
+ UnderlyingType(TypeOf(V2)) != i1 |
+ N == NumValuedInsts |
+ NumBasicBlocks < ExpectedBasicBlocks |
+ |
+**Updates** |
+ |
+.. naclcode:: |
+ |
+ ++NumValuedInsts; |
+ TypeOf(%vN) = T |
+ |
+**Examples** |
+ |
+.. naclcode:: |
+ |
+ function i32 @f0(i32 %p0, i32 %p1) { |
+ blocks: 1; |
+ %b0: |
+ %v0 = ashr i32 %p0, %p1; |
+ %v1 = ashr i32 %v0, %p1; |
+ ret i32 %v1; |
+ } |
+ |
+The corresponding records are: |
+ |
+.. naclcode:: |
+ |
+ 1: <65535, 12, 2> |
+ 3: <1, 1> |
+ 3: <2, 2, 1, 9> |
+ 3: <2, 1, 2, 9> |
+ 3: <10, 1> |
+ 0: <65534> |
+ |
+Logical And |
+^^^^^^^^^^^ |
+ |
+The *and* instruction returns the bitwise logical and of its two operands. |
+ |
+**Syntax** |
+ |
+.. naclcode:: |
+ |
+ %vN = and T V1, V2; <A> |
+ |
+**Record** |
+ |
+.. naclcode:: |
+ |
+ AA: <2, VV1, VV2, 10> |
+ |
+**Semantics** |
+ |
+This instruction performs a bitwise logical and of its arguments. Arguments |
+*V1* and *V2*, and the result *%vN* must be of type *T*. *T* nust be an |
+integral, or a vector of integrals. *N* is defined by the record position, |
+defining the corresponding value generated by the instruction. *A* is the |
+(optional) abbreviation associated with the corresponding record. |
+ |
+The truth table used for the *and* instruction is: |
+ |
+===== ===== ====== |
+Arg 1 Arg 2 Result |
+===== ===== ====== |
+0 0 0 |
+0 1 0 |
+1 0 0 |
+1 1 1 |
+===== ===== ====== |
+ |
+**Constraints** |
+ |
+.. naclcode:: |
+ |
+ AA == AbbrevIndex(A) |
+ VV1 == RelativeIndex(V1) |
+ VV2 == RelativeIndex(V2) |
+ T == TypeOf(V1) == TypeOf(V2) |
+ IsInteger(UnderlyingType(T))) |
+ N == NumValuedInsts |
+ NumBasicBlocks < ExpectedBasicBlocks |
+ |
+**Updates** |
+ |
+.. naclcode:: |
+ |
+ ++NumValuedInsts; |
+ TypeOf(%vN) = T |
+ |
+**Examples** |
+ |
+.. naclcode:: |
+ |
+ function i32 @f0(i32 %p0, i32 %p1) { |
+ blocks: 1; |
+ %b0: |
+ %v0 = and i32 %p0, %p1; |
+ %v1 = and i32 %v0, %p1; |
+ ret i32 %v1; |
+ } |
+ |
+The corresponding records are: |
+ |
+.. naclcode:: |
+ |
+ 1: <65535, 12, 2> |
+ 3: <1, 1> |
+ 3: <2, 2, 1, 10> |
+ 3: <2, 1, 2, 10> |
+ 3: <10, 1> |
+ 0: <65534> |
+ |
+Logical Or |
+^^^^^^^^^^ |
+ |
+The *or* instruction returns the bitwise logical inclusive or of its |
+two operands. |
+ |
+**Syntax** |
+ |
+.. naclcode:: |
+ |
+ %vN = or T V1, V2; <A> |
+ |
+**Record** |
+ |
+.. naclcode:: |
+ |
+ AA: <2, VV1, VV2, 11> |
+ |
+**Semantics** |
+ |
+This instruction performs a bitwise logical inclusive or of its arguments. |
+Arguments *V1* and *V2*, and the result *%vN* must be of type *T*. *T* nust be |
+an integral, or a vector of integrals. *N* is defined by the record position, |
+defining the corresponding value generated by the instruction. *A* is the |
+(optional) abbreviation associated with the corresponding record. |
+ |
+The truth table used for the *or* instruction is: |
+ |
+===== ===== ====== |
+Arg 1 Arg 2 Result |
+===== ===== ====== |
+0 0 0 |
+0 1 1 |
+1 0 1 |
+1 1 1 |
+===== ===== ====== |
+ |
+**Constraints** |
+ |
+.. naclcode:: |
+ |
+ AA == AbbrevIndex(A) |
+ VV1 == RelativeIndex(V1) |
+ VV2 == RelativeIndex(V2) |
+ T == TypeOf(V1) == TypeOf(V2) |
+ IsInteger(UnderlyingType(T))) |
+ N == NumValuedInsts |
+ NumBasicBlocks < ExpectedBasicBlocks |
+ |
+**Updates** |
+ |
+.. naclcode:: |
+ |
+ ++NumValuedInsts; |
+ TypeOf(%vN) = T |
+ |
+**Examples** |
+ |
+.. naclcode:: |
+ |
+ function i32 @f0(i32 %p0, i32 %p1) { |
+ blocks: 1; |
+ %b0: |
+ %v0 = or i32 %p0, %p1; |
+ %v1 = or i32 %v0, %p1; |
+ ret i32 %v1; |
+ } |
+ |
+The corresponding records are: |
+ |
+.. naclcode:: |
+ |
+ 1: <65535, 12, 2> |
+ 3: <1, 1> |
+ 3: <2, 2, 1, 11> |
+ 3: <2, 1, 2, 11> |
+ 3: <10, 1> |
+ 0: <65534> |
+ |
+Logical Xor |
+^^^^^^^^^^^ |
+ |
+The *xor* instruction returns the bitwise logical exclusive or of its |
+two operands. |
+ |
+**Syntax** |
+ |
+.. naclcode:: |
+ |
+ %vN = xor T V1, V2; <A> |
+ |
+**Record** |
+ |
+.. naclcode:: |
+ |
+ AA: <2, VV1, VV2, 12> |
+ |
+**Semantics** |
+ |
+This instruction performs a bitwise logical exclusive or of its |
+arguments. Arguments *V1* and *V2*, and the result *%vN* must be of |
+type *T*. *T* nust be an integral, or a vector of integrals. *N* is |
+defined by the record position, defining the corresponding value |
+generated by the instruction. *A* is the (optional) abbreviation |
+associated with the corresponding record. |
+ |
+The truth table used for the *or* instruction is: |
+ |
+===== ===== ====== |
+Arg 1 Arg 2 Result |
+===== ===== ====== |
+0 0 0 |
+0 1 1 |
+1 0 1 |
+1 1 0 |
+===== ===== ====== |
+ |
+**Constraints** |
+ |
+.. naclcode:: |
+ |
+ AA == AbbrevIndex(A) |
+ A1 == RelativeIndex(V1) |
+ A2 == RelativeIndex(V2) |
+ T == TypeOf(V1) == TypeOf(V2) |
+ IsInteger(UnderlyingType(T))) |
+ N == NumValuedInsts |
+ NumBasicBlocks < ExpectedBasicBlocks |
+ |
+**Updates** |
+ |
+.. naclcode:: |
+ |
+ ++NumValuedInsts; |
+ TypeOf(%vN) = T |
+ |
+**Examples** |
+ |
+.. naclcode:: |
+ |
+ function i32 @f0(i32 %p0, i32 %p1) { |
+ blocks: 1; |
+ %b0: |
+ %v0 = xor i32 %p0, %p1; |
+ %v1 = xor i32 %v0, %p1; |
+ ret i32 %v1; |
+ } |
+ |
+The corresponding records are: |
+ |
+.. naclcode:: |
+ |
+ 1: <65535, 12, 2> |
+ 3: <1, 1> |
+ 3: <2, 2, 1, 12> |
+ 3: <2, 1, 2, 12> |
+ 3: <10, 1> |
+ 0: <65534> |
+ |
+Floating Binary Instructions |
jvoung (off chromium)
2014/06/06 20:09:15
Floating Point Binary?
Karl
2014/06/30 22:09:03
Done.
|
+------------------------------ |
+ |
+Floating Binary instructions require two operands of the same type, execute an |
Jim Stichnoth
2014/06/06 18:24:49
Do you want binary capitalized?
Karl
2014/06/30 22:09:05
Done.
|
+operation on them, and produce a value. The value may represent multiple values |
+if the type is a vector type. The result value always has the same type as its |
+operands. |
+ |
+Float Add |
+^^^^^^^^^ |
+ |
+The float add instruction returns the sum of its two arguments. Both arguments |
+and the result must be of the same type. That type must be floating, or a |
+floating vector type. |
+ |
+**Syntax** |
+ |
+.. naclcode:: |
+ |
+ %vN = add T V1, V2; <A> |
+ |
+**Record** |
+ |
+ AA: <2, VV1, VV2, 0> |
+ |
+**Semantics** |
+ |
+The float add instruction returns the sum of its two arguments. Arguments *V1* |
+and *V2* and the result *%vN* must be of type *T*. *T* must be a floating type, |
+or a floating vector type. *N* is defined by the record position, defining the |
+corresponding value generated by the instruction. *A* is the (optional) |
+abbreviation associated with the corresponding record. |
+ |
+**Constraints** |
+ |
+.. naclcode:: |
+ |
+ AA == AbbrevIndex(A) |
+ VV1 == RelativeIndex(V1) |
+ VV2 == RelativeIndex(V2) |
+ T == TypeOf(V1) == TypeOf(V2) |
+ IsFloat(UnderlyingType(T)) |
+ N == NumValuedInsts |
+ NumBasicBlocks < ExpectedBasicBlocks |
+ |
+**Updates** |
+ |
+.. naclcode:: |
+ |
+ ++NumValuedInsts; |
+ TypeOf(%vN) = T |
+ |
+**Examples** |
+ |
+.. naclcode:: |
+ |
+ function float @f0(float %p0, float %p1) { |
+ blocks: 1; |
+ %b0: |
+ %v0 = add float %p0, %p1; |
+ %v1 = add float %p0, %v0; |
+ ret float %v1; |
+ } |
+ |
+The corresponding records are: |
+ |
+.. naclcode:: |
+ |
+ 1: <65535, 12, 2> |
+ 3: <1, 1> |
+ 3: <2, 2, 1, 0> |
+ 3: <2, 3, 1, 0> |
+ 3: <10, 1> |
+ 0: <65534> |
+ |
+Float Subtract |
+^^^^^^^^^^^^^^ |
+ |
+The floatsubtract instruction returns the difference of its two arguments. Both |
Jim Stichnoth
2014/06/06 18:24:46
float subtract
Karl
2014/06/30 22:09:05
Done.
|
+arguments and the result must be of the same type. That type must be a floating, |
+or an floating based vector type. |
Jim Stichnoth
2014/06/06 18:24:48
an floating --> a floating
Karl
2014/06/30 22:09:05
Done.
|
+ |
+**Syntax** |
+ |
+.. naclcode:: |
+ |
+ %vN = sub T V1, V2; <a> |
+ |
+**Record** |
+ |
+.. naclcode:: |
+ |
+ AA: <2, VV1, VV2, 1> |
+ |
+**Semantics** |
+ |
+The float subtract instruction returns the difference of its two |
+arguments. Arguments *V1* and *V2*, and the result *%vN* must be of type |
+*T*. *T* must be an floating type, or a floating vector type. *N* is defined by |
Jim Stichnoth
2014/06/06 18:24:49
a floating
Karl
2014/06/30 22:09:05
Done.
|
+the record position, defining the corresponding value generated by the |
+instruction. *A* is the (optional) abbreviation ¯associated with the |
Jim Stichnoth
2014/06/06 18:24:49
You have an interesting unicode character between
Karl
2014/06/30 22:09:05
Done.
|
+corresponding record. |
+ |
+**Constraints** |
+ |
+.. naclcode:: |
+ |
+ AA == AbbrevIndex(A) |
+ VV1 == RelativeIndex(V1) |
+ VV2 == RelativeIndex(V2) |
+ T == TypeOf(V1) == TypeOf(V2) |
+ IsFloat(UnderlyingType(T)) |
+ N == NumValuedInsts |
+ NumBasicBlocks < ExpectedBasicBlocks |
+ |
+**Updates** |
+ |
+.. naclcode:: |
+ |
+ ++NumValuedInsts; |
+ TypeOf(%vN) = T |
+ |
+**Examples** |
+ |
+.. naclcode:: |
+ |
+ function float @f0(float %p0, float %p1) { |
+ blocks: 1; |
+ %b0: |
+ %v0 = sub float %p0, %p1; |
+ %v1 = sub float %p0, %v0; |
+ ret float %v1; |
+ } |
+ |
+The corresponding records are: |
+ |
+.. naclcode:: |
+ |
+ 1: <65535, 12, 2> |
+ 3: <1, 1> |
+ 3: <2, 2, 1, 1> |
+ 3: <2, 3, 1, 1> |
+ 3: <10, 1> |
+ 0: <65534> |
+ |
+Float Multiply |
+^^^^^^^^^^^^^^ |
+ |
+The float multiply instruction returns the product of its two arguments. Both |
+arguments and the result must be of the same type. That type must be floating, |
+or a floating based vector type. |
+ |
+**Syntax** |
+ |
+.. naclcode:: |
+ |
+ &vN = mul T V1, V2; <A> |
+ |
+**Record** |
+ |
+.. naclcode:: |
+ |
+ AA: <2, VV1, VV2, 2> |
+ |
+**Semantics** |
+ |
+The multiply instruction returns the product of its two arguments. Arguments |
+*V1* and *V2*, and the result *%vN* must be of type *T*. *T* must be an |
+floating type, or a floating vector type. *N* is defined by the record position, |
+defining the corresponding value generated by the instruction. *A* is the |
+(optional) abbreviation associated with the corresponding record. |
+ |
+**Constraints** |
+ |
+.. naclcode:: |
+ |
+ AA == AbbrevIndex(A) |
+ VV1 == RelativeIndex(V1) |
+ VV2 == RelativeIndex(V2) |
+ T == TypeOf(V1) == TypeOf(V2) |
+ IsFloat(UnderlyingType(T)) |
+ N == NumValuedInsts |
+ NumBasicBlocks < ExpectedBasicBlocks |
+ |
+**Updates** |
+ |
+.. naclcode:: |
+ |
+ ++NumValuedInsts; |
+ TypeOf(%vN) = T |
+ |
+**Examples** |
+ |
+.. naclcode:: |
+ |
+ function float @f0(float %p0, float %p1) { |
+ blocks: 1; |
+ %b0: |
+ %v0 = mul float %p0, %p1; |
+ %v1 = mul float %p0, %v0; |
+ ret float %v1; |
+ } |
+ |
+The corresponding records are: |
+ |
+.. naclcode:: |
+ |
+ 1: <65535, 12, 2> |
+ 3: <1, 1> |
+ 3: <2, 2, 1, 2> |
+ 3: <2, 3, 1, 2> |
+ 3: <10, 1> |
+ 0: <65534> |
+ |
+Float Divide |
+^^^^^^^^^^^^ |
+ |
+The float divide instruction returns the quotient of its two arguments. Both |
+arguments and the result must be of the same type. That type must be a floating |
+type, or a floating based vector type. |
+ |
+**Syntax** |
+ |
+.. naclcode:: |
+ |
+ %vN = div T V1, V2; <A> |
+ |
+**Record** |
+ |
+.. naclcode:: |
+ |
+ AA: <2, V1, V2, 4> |
+ |
+**Semantics** |
+ |
+The float divide instruction returns the quotient of its two |
+arguments. Arguments *V1* and *V2*, and the result *%vN* must be of type |
+*T*. *T* must be a floating type, or a floating vector type. *N* is defined by |
+the record position, defining the corresponding value generated by the |
+instruction. *A* is the (optional) abbreviation associated with the |
+corresponding record. |
+ |
+**Constraints** |
+ |
+.. naclcode:: |
+ |
+ AA == AbbrevIndex(A) |
+ VV1 == RelativeIndex(V1) |
+ VV22 == RelativeIndex(V2) |
+ T == TypeOf(V1) == TypeOf(V2) |
+ IsFloat(UnderlyingType(T)) |
+ N == NumValuedInsts |
+ NumBasicBlocks < ExpectedBasicBlocks |
+ |
+**Updates** |
+ |
+.. naclcode:: |
+ |
+ ++NumValuedInsts; |
+ TypeOf(%vN) = T |
+ |
+**Examples** |
+ |
+.. naclcode:: |
+ |
+ function double @f0(double %p0, double %p1) { |
+ blocks: 1; |
+ %b0: |
+ %v0 = div double %p0, %p1; |
+ %v1 = div double %p0, %v0; |
+ ret double %v1; |
+ } |
+ |
+The corresponding records are: |
+ |
+.. naclcode:: |
+ |
+ 1: <65535, 12, 2> |
+ 3: <1, 1> |
+ 3: <2, 2, 1, 4> |
+ 3: <2, 3, 1, 4> |
+ 3: <10, 1> |
+ 0: <65534> |
+ |
+Float Remainder |
+^^^^^^^^^^^^^^^ |
+ |
+The float remainder instruction returns the remainder of the quotient of its two |
+arguments. Both arguments and the result must be of the same type. That type |
+must be a floating type, or a floating based vector type. |
+ |
+**Syntax** |
+ |
+.. naclcode:: |
+ |
+ %vN = rem T V1, V2; <A> |
+ |
+**Record** |
+ |
+.. naclcode:: |
+ |
+ AA: <2, VV1, VV2, 6> |
+ |
+**Semantics** |
+ |
+The float remainder instruction returns the remainder of the quotient of its two |
+arguments. Arguments *V1* and *V2*, and the result *%vN* must be of type |
+*T*. *T* must be a floating type, or a floating vector type. *N* is defined by |
+the record position, defining the corresponding value generated by the |
+instruction. *A* is the (optional) abbreviation associated with the |
+corresponding record. |
+ |
+**Constraints** |
+ |
+.. naclcode:: |
+ |
+ AA == AbbrevIndex(A) |
+ VV1 == RelativeIndex(V1) |
+ VV2 == RelativeIndex(V2) |
+ T == TypeOf(V1) == TypeOf(V2) |
+ IsFloat(UnderlyingType(T)) |
+ N == NumValuedInsts |
+ NumBasicBlocks < ExpectedBasicBlocks |
+ |
+**Updates** |
+ |
+.. naclcode:: |
+ |
+ ++NumValuedInsts; |
+ TypeOf(%vN) = T |
+ |
+**Examples** |
+ |
+.. naclcode:: |
+ |
+ function double @f0(double %p0, double %p1) { |
+ blocks: 1; |
+ %b0: |
+ %v0 = rem double %p0, %p1; |
+ %v1 = rem double %p0, %v0; |
+ ret double %v1; |
+ } |
+ |
+The corresponding records are: |
+ |
+.. naclcode:: |
+ |
+ 1: <65535, 12, 2> |
+ 3: <1, 1> |
+ 3: <2, 2, 1, 6> |
+ 3: <2, 3, 1, 6> |
+ 3: <10, 1> |
+ 0: <65534> |
+ |
+Memory creation and access Instructions |
Jim Stichnoth
2014/06/06 18:24:47
Do something more consistent with capitalization.
|
+--------------------------------------- |
+ |
+A key design point of SSA-based representation is how it represents |
+memory. In PNaCl bitcode files, no memory locations are in SSA |
+form. This makes things very simple. |
+ |
+Alloca Instruction |
+^^^^^^^^^^^^^^^^^^ |
+ |
+The *alloca* instruction allocates memory on the stack frame of the |
+currently executing function. This memory is automatically released |
+when the function returns to its caller. |
+ |
+**Syntax** |
+ |
+.. naclcode:: |
+ |
+ %vN = alloca i8, i32 S, align V; <A> |
+ %vN = alloca i8, i32 S; <A> |
+ |
+**Record** |
+ |
+.. naclcode:: |
+ |
+ AA: <19, SS, VV> |
+ |
+**Semantics** |
+ |
+The *alloca* instruction allocates memory on the stack frame of the currently |
+executing function. The resulting value is a pointer to the allocated memory |
+(i.e. of type i32). *S* is the number of bytes that are allocated on the |
+stack. *S* must be of integral type i32. *V* is the aligment of the generated |
Jim Stichnoth
2014/06/06 18:24:47
alignment
Karl
2014/06/30 22:09:05
Done.
|
+stack address. *A* is the corresponding number of bits associated with the |
+record. |
+ |
+Alignment must be a power of 2. A value of 0 means that the address |
+has the ABI alignment of the target. If alignment is not specified, |
+zero is used. Alignment on the stack is guaranteed to be aligned to at least |
+the boundary specified by the alignment. |
+ |
+TODO(kschimpf) Other alignment issues? |
+ |
+**Constraints** |
+ |
+.. naclcode:: |
+ |
+ AA == AbbrevIndex(A) |
+ VV == Log2(V+1) |
+ SS == RelativeIndex(S) |
+ i32 == TypeOf(S) |
+ N == NumValuedInsts |
+ NumBasicBlocks < ExpectedBasicBlocks |
+ |
+**Updates** |
+ |
+.. naclcode:: |
+ |
+ ++NumValuedInsts; |
+ TypeOf(%vN) = i32; |
+ |
+**Examples** |
+ |
+The following instructions allocates memory for a 32-bit integer and a |
Jim Stichnoth
2014/06/06 18:24:48
instructions allocate
|
+64-bit floating value: |
+ |
+.. naclcode:: |
+ |
+ function void @f() { |
+ blocks: 1; |
+ constants { |
+ i32: |
+ %c0 = 4; // == sizeof(i32) |
+ %c1 = 8; // == sizeof(double) |
+ } |
+ %b0: |
+ %v0 = alloca i8, i32 %c0; |
+ %v1 = alloca i8, i32 %c1; |
+ ret; |
+ } |
+ |
+Assuming *TypeId(i32) == @t1*, the corresponding records are: |
+ |
+.. naclcode:: |
+ |
+ 1: <65535, 12, 2> |
+ 3: <1, 1> |
+ 1: <65535, 11, 2> |
+ 3: <1, 1> |
+ 3: <4, 8> |
+ 3: <4, 16> |
+ 0: <65534> |
+ 3: <19, 2, 0> |
+ 3: <19, 2, 0> |
+ 3: <10> |
+ 0: <65534> |
+ |
+Load Instruction |
+^^^^^^^^^^^^^^^^ |
+ |
+The *load* instruction is used to read from memory. |
+ |
+**Syntax** |
+ |
+.. naclcode:: |
+ |
+ %vN = load T* P, align V; <A> |
+ |
+**Record** |
+ |
+.. naclcode:: |
+ |
+ AA: <20, PP, VV, TT> |
+ |
+**Semantics** |
+ |
+The load instruction is used to read from memory. *P* is identifier of the |
Jim Stichnoth
2014/06/06 18:24:48
is the identifier
Karl
2014/06/30 22:09:03
Done.
|
+memory address to read. The type of *P* must be an i32 integer. *T* is the type |
+of value to read. *V* is the alignment of the memory address. *A* is the |
jvoung (off chromium)
2014/06/06 20:09:14
Should we say more about alignment? What happens i
Karl
2014/06/30 22:09:05
Done.
|
+(optional) abbreviation associated with the record. |
+ |
+Type *T* must be an integral or floating type. Both float and double types |
+are allowed for floating types. All integral types except i1 is allowed. |
Jim Stichnoth
2014/06/06 18:24:47
are allowed
Karl
2014/06/30 22:09:03
Done.
|
+ |
+Valid alignment *V* values are: |
+ |
+=== ================= |
+*V* Types |
+=== ================= |
+1 i8, i16, i32, i64 |
+4 float |
+8 double |
+=== ================= |
+ |
+**Constraints** |
+ |
+ AA == AbbrevIndex(A) |
+ i32 == TypeOf(P) |
+ PP == RelativeIndex(P) |
+ VV == Log2(V+1) |
+ %tTT == TypeID(T) |
+ N == NumValuedInsts |
+ NumBasicBlocks < ExpectedBasicBlocks |
+ |
+**Updates** |
+ |
+.. naclcode:: |
+ |
+ ++NumValuedInsts; |
+ TypeOf(%vN) = T; |
+ |
+**Examples** |
+ |
+The following instructions load an i32 integer and a 64-bit floating value: |
+ |
+.. naclcode:: |
+ |
+ function void @f(i32 %p0) { |
+ blocks: 1; |
+ %b0: |
+ %v0 = load i32* %p0, align 1; |
+ %v1 = load double* %v0, align 8; |
+ ret; |
+ } |
+ |
+The corresponding records are: |
+ |
+.. naclcode:: |
+ |
+ 1: <65535, 12, 2> |
+ 3: <1, 1> |
+ 3: <20, 1, 1> |
+ 3: <20, 1, 4> |
+ 3: <10> |
+ 0: <65534> |
+ |
+Store Instruction |
+^^^^^^^^^^^^^^^^^ |
+ |
+The *store* instruction is used to write to memory. |
+ |
+**Syntax** |
+ |
+.. naclcode:: |
+ |
+ store T S, T* P, align V; <A> |
+ |
+**Record** |
+ |
+.. naclcode:: |
+ |
+ AA: <24, PP, SS, VV> |
+ |
+**Semantics** |
+ |
+The store instruction is used to write to memory. *P* is the identifier of the |
+memory address to write to. The type of *P* must be an i32 integer. *T* is the |
+type of value to store. *S* is the value to store, and must be of type *T*. *V* |
+is the alignment of the memory address. *A* is the (optional) abbreviation |
+index associated with the record. |
+ |
+Type *T* must be an integral or floating type. Both float and double types |
+are allowed for floating types. All integral types except i1 is allowed. |
Jim Stichnoth
2014/06/06 18:24:46
are allowed
Karl
2014/06/30 22:09:03
Done.
|
+ |
+Valid alignment *V* values are: |
+ |
+=== ================= |
+*V* Types |
+=== ================= |
+1 i8, i16, i32, i64 |
+4 float |
+8 double |
+=== ================= |
+ |
+**Constraints** |
+ |
+.. naclcode:: |
+ |
+ AA == AbbrevIndex(A) |
+ i32 == TypeOf(P) |
+ PP == RelativeIndex(P) |
+ VV == Log2(V+1) |
+ NumBasicBlocks < ExpectedBasicBlocks |
+ |
+**Examples** |
+ |
+The following instructions store an i32 integer and a 32-bit floating |
+value. |
+ |
+.. naclcode:: |
+ |
+ function void @f(i32 %p0, i32 %p1, i32 %p2, float %p3) { |
+ blocks: 1; |
+ %b0: |
+ store i32 %p1, i32* %p2, align 1; |
+ store float %p3, float* %p3, align 4; |
+ ret; |
+ } |
+ |
+The corresponding records are: |
+ |
+.. naclcode:: |
+ |
+ 1: <65535, 12, 2> |
+ 3: <1, 1> |
+ 3: <24, 4, 3, 1> |
+ 3: <24, 1, 2, 4> |
+ 3: <10> |
+ 0: <65534> |
+ |
+Conversion Instructions |
+----------------------- |
+ |
+Conversion instructions all take a single operand and a type. The |
+value is converted to the corresponding type. |
+ |
+Integer truncating Instruction |
Jim Stichnoth
2014/06/06 18:24:48
capitalization?
Karl
2014/06/30 22:09:06
Done.
|
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
+ |
+The integer truncating instruction takes a value to truncate, and a type |
+defining the truncated type. Both types must be integer types, or integral |
+vectors of the same size. The bit size of the value must be larger than the bit |
+size of the destination type. Equal sized types are not allowed. |
+ |
+**Syntax** |
+ |
+.. naclcode:: |
+ |
+ %vN = trunc T1 V to T2; <A> |
+ |
+**Record** |
+ |
+.. naclcode:: |
+ |
+ AA: <3, VV, TT2, 0> |
+ |
+**Semantics** |
+ |
+The integer truncating instruction takes a value *V*, and truncates to type |
+*T2*. *A* is the (optional) abbreviation associated with the corresponding |
+record. Both *T1* and *T2* must be integer types, or integral vectors of the |
jvoung (off chromium)
2014/06/06 20:09:14
same number of elements instead of same "size" ?
Karl
2014/06/30 22:09:04
This was implied by the constratiants, but I agree
|
+same size. |
+ |
+**Constraints** |
+ |
+.. naclcode:: |
+ |
+ AA == AbbrevIndex(A) |
+ TypeOf(V) = T1 |
jvoung (off chromium)
2014/06/06 20:09:15
Earlier you use == for these TypeOf constraints, b
Karl
2014/06/30 22:09:05
You are right. I am inconsistent with this. Fixing
|
+ *VV* == RelativeIndex(*V*) |
+ %tTT2 = TypeID(T2) |
+ BitSizeOf(UnderlyingType(T1)) > BitSizeOf(UnderlyingType(T2)) |
+ UnderlyingCount(T1) == UnderlyingCount(T2) |
+ IsInteger(UnderlyingType(T1)) |
+ IsInteger(UnderlyingType(T2)) |
+ N == NumValuedInsts |
+ NumBasicBlocks < ExpectedBasicBlocks |
+ |
+**Updates** |
+ |
+.. naclcode:: |
+ |
+ ++NumValuedInsts; |
+ TypeOf(%vN) = T2; |
+ |
+**Examples** |
+ |
+.. naclcode:: |
+ |
+ %v10 = trunc i32 %v9 to i8; |
+ |
+Assuming |
+ |
+.. naclcode:: |
+ |
+ @t2 = i8; |
+ |
+the corresponding record is: |
+ |
+.. naclcode:: |
+ |
+ <3, 1, 2, 0> |
+ |
+Floating truncating Instruction |
Jim Stichnoth
2014/06/06 18:24:49
capitalization?
|
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
+ |
+The floating truncating instruction takes a value to truncate, and a type |
+defining the truncated type. Both types must be floating types, or floating |
+vectors of the same size. The bit size of the value must be larger than the bit |
+size of the destination type. Equal sized types are not allowed. |
+ |
+**Syntax** |
+ |
+.. naclcode:: |
+ |
+ %vN = fptrunc T1 V to T2; <A> |
+ |
+**Record** |
+ |
+.. naclcode:: |
+ |
+ AA: <3, VV, TT2, 7> |
+ |
+**Semantics** |
+ |
+The floating truncating instruction takes a value *V*, and truncates to type |
+*T2*. *A* is the (optional) abbreviation associated with the corresponding |
+record. Both *T1* and *T2* must be integer types, or integral vectors of the |
jvoung (off chromium)
2014/06/06 20:09:14
floating point types / vectors (seems copy pasted
Karl
2014/06/30 22:09:04
Done.
|
+same size. |
+ |
+If the value can't fit within the destination type *T2*, the results are |
+undefined. |
+ |
+**Constraints** |
+ |
+.. naclcode:: |
+ |
+ TypeOf(V) = T1 |
+ double == UnderlyingType(T1) |
+ float == UnderlyingType(T2) |
+ *VV* == RelativeIndex(*V*) |
+ %tTT2 = TypeID(T2) |
+ BitSizeOf(UnderlyingType(T1)) > BitSizeOf(UnderlyingType(T2)) |
+ UnderlyingCount(T1) == UnderlyingCount(T2) |
+ IsFloat(UnderlyingType(T1)) |
+ IsFloat(UnderlyingType(T2)) |
+ N == NumValuedInsts |
+ NumBasicBlocks < ExpectedBasicBlocks |
+ |
+**Updates** |
+ |
+.. naclcode:: |
+ |
+ ++NumValuedInsts; |
+ TypeOf(%vN) = T2; |
+ |
+**Examples** |
+ |
+.. naclcode:: |
+ |
+ %v10 = fptrunc double %v9 to float; |
+ |
+Assuming |
+ |
+.. naclcode:: |
+ |
+ @t4 = float; |
+ |
+the corresponding record is: |
+ |
+.. naclcode:: |
+ |
+ <3, 1, 4, 7> |
+ |
+Zero Extending Instruction |
+^^^^^^^^^^^^^^^^^^^^^^^^^^ |
+ |
+The zero extending instruction takes an value to cast, and a type to extend it |
Jim Stichnoth
2014/06/06 18:24:47
a value
|
+to. Both types must be integer types, or integral vectors of the same size. The |
+bit size of the value must be smaller than the bitsize of the destination |
Jim Stichnoth
2014/06/06 18:24:47
bitsize --> bit size
Karl
2014/06/30 22:09:05
Done.
|
+type. Equal sized types are not allowed. |
+ |
+**Syntax** |
+ |
+.. naclcode:: |
+ |
+ %vN = zext T1 V to T2; <A> |
+ |
+**Record** |
+ |
+.. naclcode:: |
+ |
+ AA: <3, VV, TT2, 1> |
+ |
+ |
+**Semantics** |
+ |
+The zero extending instruction takes a value *V*, and expands it to type |
+*T2*. *I* is the (optional) abbreviation associated with the corresponding |
+record. Both *T1* and *T2* must be integer types, or vectors of the same number |
+of integers. |
+ |
+The instruction fills the high order bits of the value with zero bits |
+until it reaches the size of the destination type. When zero extending |
+from i1, the result will always be either 0 or 1. |
+ |
+**Constraints** |
+ |
+.. naclcode:: |
+ |
+ AA == AbbrevIndex(A) |
+ TypeOf(V) = T1 |
+ *VV* == RelativeIndex(*V*) |
+ %tTT2 = TypeID(T2) |
+ BitSizeOf(UnderlyingType(T1)) < BitSizeOf(UnderlyingType(T2)) |
+ UnderlyingCount(T1) == UnderlyingCount(T2) |
+ IsInteger(UnderlyingType(T1)) |
+ IsInteger(UnderlyingType(T2)) |
+ N == NumValuedInsts |
+ NumBasicBlocks < ExpectedBasicBlocks |
+ |
+**Updates** |
+ |
+.. naclcode:: |
+ |
+ ++NumValuedInsts; |
+ TypeOf(%vN) = T2; |
+ |
+**Examples** |
+ |
+.. naclcode:: |
+ |
+ %v12 = zext i8 %v11 to i32; |
+ |
+Assuming |
+ |
+.. naclcode:: |
+ |
+ @t0 = i32; |
+ |
+the corresponding record is: |
+ |
+.. naclcode:: |
+ |
+ <3, 1, 0, 2> |
+ |
+Sign Extending Instruction |
+^^^^^^^^^^^^^^^^^^^^^^^^^^ |
+ |
+The sign extending instruction takes an value to cast, and a type to |
Jim Stichnoth
2014/06/06 18:24:47
a value
Karl
2014/06/30 22:09:04
Done.
|
+extend it to. Both types must be integer types, or vectors of the same |
+number of integers. The bit size of the value must be smaller than the |
+bitsize of the destination type. Equal sized types are not allowed. |
Jim Stichnoth
2014/06/06 18:24:47
bit size
Karl
2014/06/30 22:09:04
Done.
|
+ |
+**Syntax** |
+ |
+.. naclcode:: |
+ |
+ %vN = sext T1 V to T2; <I> |
+ |
+**Record** |
+ |
+.. naclcode:: |
+ |
+ I: <3, VV, TT2, 2> |
+ |
+ |
+**Semantics** |
+ |
+The sign extending instruction takes a value *V*, and expands it to |
+type *T2*. *VV* is the relative index of *V*. *I* is the (optional) |
+abbreviation associated with the corresponding record. Both *T1* and |
+*T2* must be integer types, or vectors of the same number of integers. |
+ |
+When sign extending, the instruction fills the high order bits of the |
+value with the (current) high order bit of the value. When sign |
+extending from i1, the extension always results in -1 or 0. |
+ |
+**Constraints** |
+ |
+.. naclcode:: |
+ |
+ TypeOf(V) = T1 |
+ *VV* == RelativeIndex(*V*) |
+ %tTT2 = TypeID(T2) |
+ BitSizeOf(UnderlyingType(T1)) < BitSizeOf(UnderlyingType(T2)) |
+ UnderlyingCount(T1) == UnderlyingCount(T2) |
+ IsInteger(UnderlyingType(T1)) |
+ IsInteger(UnderlyingType(T2)) |
+ N == NumValuedInsts |
+ NumBasicBlocks < ExpectedBasicBlocks |
+ |
+**Updates** |
+ |
+.. naclcode:: |
+ |
+ ++NumValuedInsts; |
+ TypeOf(%vN) = T2; |
+ |
+**Examples** |
+ |
+.. naclcode:: |
+ |
+ %v12 = sext i8 %v11 to i32; |
+ |
+Assuming |
+ |
+.. naclcode:: |
+ |
+ @t0 = i32; |
+ |
+the corresponding record is: |
+ |
+.. naclcode:: |
+ |
+ <3, 1, 0, 2> |
+ |
+fpext |
+^^^^^ |
+ |
+TODO(kschimpf) |
+ |
+fptoui |
+^^^^^^ |
+ |
+TODO(kschimpf) |
+ |
+fptosi |
+^^^^^^ |
+ |
+TODO(kschimpf) |
+ |
+sitofp |
+^^^^^^ |
+ |
+TODO(kschimpf) |
+ |
+bitcast |
+^^^^^^^ |
+ |
+TODO(kschimpf) |
+ |
+Comparison Instructions |
+----------------------- |
+ |
+TODO(kschimpf): cmp |
+ |
+Other Instructions |
+------------------ |
+ |
+TODO(kschimpf) |
+ |
+Forward type declarations |
+^^^^^^^^^^^^^^^^^^^^^^^^^ |
+ |
+TODO(kschimpf) |
+ |
+Phi Instruction |
+^^^^^^^^^^^^^^^ |
+ |
+TODO(kschimpf) |
+ |
+ |
+Select Instruction |
+^^^^^^^^^^^^^^^^^^ |
+ |
+TODO(kschimpf) |
+ |
+Call Instructions |
+^^^^^^^^^^^^^^^^^ |
+ |
+TODO(kschimpf) |
+ |
+Intrinsic Functions |
+------------------- |
+ |
+TODO(kschimpf) |
+ |
+Support Functions |
+================= |
+ |
+Defines functions used to convert syntactic representation to corresponding |
+records. |
+ |
+SignRotate |
+---------- |
+ |
+The SignRotate function encodes a signed integer in an easily compressable |
Jim Stichnoth
2014/06/06 18:24:48
compressible
Karl
2014/06/30 22:09:04
Done.
|
+form. This is done by rotating the sign bit to the rightmost bit, rather than |
+the leftmost bit. By doing this rotation, both small positive and negative |
+integers are small (unsigned) integers. Therefore, all small integers can be |
+encoded as a small (unsigned) integers. |
+ |
+The definition of SignRotate(N) is: |
+ |
+======== ============= ========= |
+Argument Value Condition |
+======== ============= ========= |
+N abs(N)<<1 N >= 0 |
+N abs(N)<<1 + 1 N < 0 |
+======== ============= ========= |
+ |
+AbsoluteIndex |
+------------- |
+ |
+Bitcode ID's of the forms *@fN*, *@gN*, *%pN*, *%cN*, and *%vN*, are combined |
+into a single index space. This can be done because of the ordering imposed by |
+PNaClAsm. All function address bitcode IDs must be defined before any of the |
+other forms of bitcode IDs. All global address bitcode IDs must be defined |
+before any local bitcode IDs. Within a function block, the parameter bitcode IDs |
+must be defined before constant IDs, and constant IDs must be defined before |
+instruction value IDs. |
+ |
+Hence, within a function block, it is safe to refer to all of these |
+bitcode IDs using a single *absolute* index. The absolute index for |
+each kind of bitcode ID is computed as follows: |
+ |
+========== ========================================================================== |
+Bitcode ID AbsoluteIndex |
+========== ========================================================================== |
+@fN N |
+@gN N + NumDefinedFcnAddresses |
+@pN N + NumDefinedFcnAddresses + NumGlobalAddresses |
+@cN N + NumDefinedFcnAddresses + NumGlobalAddresses + NumParams |
+@vN N + NumDefinedFcnAddresses + NumGlobalAddresses + NumParams + NumFcnConsts |
+========== ========================================================================== |
+ |
+RelativeIndex |
+------------- |
+ |
+Relative indices are used to refer to values within instructions of a |
+function. The relative index of an ID is always defined in terms of |
+the index associated with the next value generating instruction. It is |
+defined as follows: |
+ |
+.. naclcode:: |
+ |
+ RelativeIndex(J) = AbsoluteIndex(NumValuedInsts) - AbsoluteIndex(J) |
+ |
+AbbrevIndex |
+----------- |
+ |
+This function converts user-defined abbreviation indices to the corresponding |
+internal abbreviation index saved in the bitcode file. It adds 4 to its argument, |
Jim Stichnoth
2014/06/06 18:24:47
80-col
Karl
2014/06/30 22:09:03
Done.
|
+since there are 4 predefined internal abbreviation indices (0, 1, 2, and 3). |
+ |
+========= ============== |
+N AbbrevIndex(N) |
+========= ============== |
+undefined 3 |
+%aA A + 4 |
+@aA A + 4 |
+========= ============== |
+ |
+Log2 |
+---- |
+ |
+This is the 32-bit log2 value of its argument. |
+ |
+exp |
+--- |
+ |
+.. naclcode:: |
+ |
+ exp(n, m) |
+ |
+Denotes the *m* power of *n*. |
+ |
+BitSizeOf |
+--------- |
+ |
+Returns the number of bits needed to represent its argument (a type). |
+ |
+UnderlyingType |
+-------------- |
+ |
+Returns the primitive type of the type construct. For primitive types, |
+the *UnderlyingType* is itself. For vector types, the base type of the |
+vector is the underlying type. |
Jim Stichnoth
2014/06/06 18:24:47
What if the type is a vector of vectors? (or is t
Karl
2014/06/30 22:09:06
This isn't possible.
|
+ |
+UnderlyingCount |
+--------------- |
+ |
+Returns the number of primitive types in the construct. For primitive |
+types, the *UnderlyingCount* is 1. For vector types, it returns the |
+number of elements in the vector. |
+ |
+IsInteger |
+--------- |
+ |
+Returns true if the argument is in {i1, i8, i16, i32, i64}. |
+ |
+IsFloat |
+------- |
+ |
+Returns true if the argument is in {float, double}. |
+ |
+Abbreviations |
+------------- |
+ |
+TODO(kschimpf) |
+ |
+Introduction |
+^^^^^^^^^^^^ |
+ |
+TODO(kschimpf) |
+ |
+* Blocks |
+* Data Records |
+* Abbreviations |
+* Abbreviation Ids. |
+ |
+Bitstream Format |
+^^^^^^^^^^^^^^^^ |
+ |
+TODO(kschimpf) |
+ |
+* Header |
+* Block Structure |
+* Primitives |
+* Abbreviations |
+* BlockInfoBlock |
+ |
+The *abbreviations block* [ref] is the first block in the module buld.. The |
Jim Stichnoth
2014/06/06 18:24:46
buld?
Karl
2014/06/30 22:09:03
Done.
|
+block is divided into sections. Each section is a sequence of records. Each |
+record in the sequence defines a user-defined abbreviation. Each section |
+defines abbreviations that can be applied to all (succeeding) blocks of a |
+particular kind. These abbreviations are denoted by the (global) ID of the form |
+*@aN*. |
+ |
+Reference Implementation |
+------------------------ |
+ |
+TODO(kschimpf) |
+ |