Use these encodings to test trapz.b1 and trapnz.b1.
When a b1 value is stored in a register, only the low 8 bits are valid.
This is so we can use the various setCC instructions to generate the b1
registers.
The expansion of a heap_addr instruction depends on the type of heap and
its configuration, so this is handled by custom code.
Add a couple examples of heap access code to the language reference
manual.
Add preamble syntax for declaring static and dynamic heaps, and update
the langref section on heaps. Add IR support for heap references.
Remove the heap_load and heap_store as discussed in #144. We will use
heap_addr along with native load and store instructions in their place.
Add the heap_addr instruction and document its bounds checking
semantics.
The code to compute the address of a global variable depends on the kind
of variable, so custom legalization is required.
- Add a legalizer::globalvar module which exposes an
expand_global_addr() function. This module is likely to grow as we add
more types of global variables.
- Add a ArgumentPurpose::VMContext enumerator. This is used to represent
special 'vmctx' arguments that are used as base pointers for vmctx
globals.
The custom_legalize() method on XFormGroup can be used to call a
custom function to legalize specific opcodes.
This will be used shortly to expand global_addr which has an expansion
that depends on the details of the global variable being referenced.
Stop passing Cursor references to legalizer functions. Give them the
whole &mut Function instead. Given the whole Function reference, these
functions can create their own cursors.
This lets legalizer actions access other Function data structures like
the global variables.
See #144 for discussion.
- Add a new GlobalVar entity type both in Python and Rust.
- Define a UnaryGlobalVar instruction format containing a GlobalVar
reference.
- Add a globalvar.rs module defining the GlobalVarData with support for
'vmctx' and 'deref' global variable kinds.
Langref:
Add a section about global variables and the global_addr
instruction.
Parser:
Add support for the UnaryGlobalVar instruction format as well as
global variable declarations in the preamble.
Also move the extending loads and truncating stores into the bulkier
"Operations" section to improve the flow of the "Memory" section in the
language reference.
* Add Atom and Literal base classes to CDSL Ast. Change substitution() and copy() on Def/Apply/Rtl to support substituting Var->Union[Var, Literal]. Check in Apply() constructor kinds of passed in Literals respect instruction signature
* Change verify_semantics to check all possible instantiations of enumerated immediates (needed to descrive icmp). Add all bitvector comparison primitives and bvite; Change set_semantics to optionally accept XForms; Add semantics for icmp; Fix typing errors in semantics/{smtlib, elaborate, __init__}.py after the change of VarMap->VarAtomMap
* Forgot macros.py
* Nit obscured by testing with mypy enabled present.
* Typo
The Cursor navigation methods all just depend on the cursor's position
and layout reference. Make a CursorBase trait that provides access to
this information with methods and implement the navigation methods on
top of that.
This makes it possible to have multiple types implement the cursor
interface.
* Added Intel x86-64 encodings for 64bit loads and store instructions
* Using GPR registers instead of ABCD for istore8 with REX prefix
Fixed testing of 64bit intel encoding
* Emit REX and REX-less encodings for optional REX prefix
Value renumbering in binary64.cton
The generated legalization code needs to evaluate any instruction
patterns on the input pattern being matched.
Emit predicate checking code inside the InstructionFormat pattern match
where all the instruction's immediate fields are available to the
predicate code.
Also make sure an `args` array is available for any type predicates to
evaluate correctly.
We already do this for the encoding tables, but the instruction
predicates computed by Apply.inst_predicate() did not include them.
Make sure we don't duplicate the type check in the Encoding constructor
when passed an Apply AST node.
Each input pattern can have a predicate in addition to an opcode being
matched. When an opcode has multiple patterns, execute the first pattern
with a true predicate.
The predicates can be type checks or instruction predicates checking
immediate fields.
Replace the isa::Legalize enumeration with a function pointer. This
allows an ISA to define its own specific legalization actions instead of
relying on the default two.
Generate a LEGALIZE_ACTIONS table for each ISA which contains
legalization function pointers indexed by the legalization codes that
are already in the encoding tables. Include this table in
isa/*/enc_tables.rs.
Give the `Encodings` iterator a reference to the action table and change
its `legalize()` method to return a function pointer instead of an
ISA-specific code.
The Result<> returned from TargetIsa::encode() no longer implements
Debug, so eliminate uses of unwrap and expect on that type.
The following instructions have simple encodings:
- bitcast.f32.i32
- bitcast.i32.f32
- bitcast.f64.i64
- bitcast.i64.f64
- fpromote.f64.f32
- fdemote.f32.f64
Also add helper functions enc_flt() and enc_i32_i64 to
intel.encodings.py for generating the common set of encodings for an
instruction: I32, I64 w/REX, I64 w/o REX.
Instructions will multiple type variables can now use `any` to indicate
encodings that don't care about the value of a secondary type variable:
ishl.i32.any instead of ishl.i32.i32
This is only allowed for secondary type variables (which are converted
to instruction predicates). The controlling type variable must still be
fully specified because it is used to key the encoding tables.
Predicate numbers are available in the maps
isa.settings.predicate_number and isa.instp_number instead.
Like the name field, predicate numbers don't interact well with
unique_pred().
The name of a predicate was only ever used for named settings that are
computed as a boolean expression of other settings.
- Record the names of these settings in named_predicates instead.
- Remove the name field from all predicates.
Named predicates does not interact well with the interning of predicates
through isa.unique_pred().
The encoding tables are keyed by the controlling type variable only. We
need to distinguish different encodings for instructions with multiple
type variables.
Add a TypePredicate instruction predicate which can check the type of an
instruction value operand. Combine type checks into the instruction
predicate for instructions with more than one type variable.
Add Intel encodings for fcvt_from_sint.f32.i64 which can now be
distinguished from fcvt_from_sint.f32.i32.
The encoding list compression algorithm is not the sharpest knife in the
drawer. It can reuse subsets of I64 encoding lists for I32 instructions,
but only when the I64 lists are defined first.
With this change and the previous change to the encoding list format, we
get the following table sizes for the Intel ISA:
ENCLISTS: 1478 B -> 662 B
LEVEL2: 1072 B (unchanged)
LEVEL1: 32 B -> 48 B
Total: 2582 B -> 1782 B (-31%)
Encodings has a 16-bit "recipe" field, but even Intel only has 57
recipes currently, so it is unlikely that we will ever need to full
range. Use this to represent encoding lists more compactly.
Change the encoding list to a format that:
- Doesn't need a predicate entry before every encoding entry.
- Doesn't need a terminator after the list for each instruction.
- Supports multiple "stop codes" for configurable guidance of the
legalizer.
The encoding scheme has these limits:
- 2*NR + NS <= 0x1000
- INSTP + ISAP <= 0x1000
Where:
- NR is the number of recipes in an ISA,
- NS is the number of stop codes (legalization actions).
- INSTP is the number of instruction predicates.
- ISAP is the number of discrete ISA predicates.