Merge branch 'master' into no_std
This commit is contained in:
@@ -5,6 +5,7 @@ rust:
|
||||
- nightly
|
||||
matrix:
|
||||
allow_failures:
|
||||
- rust: beta
|
||||
- rust: nightly
|
||||
dist: trusty
|
||||
sudo: false
|
||||
|
||||
41
README.rst
41
README.rst
@@ -6,23 +6,52 @@ Cretonne is a low-level retargetable code generator. It translates a `target-ind
|
||||
intermediate representation <https://cretonne.readthedocs.io/en/latest/langref.html>`_ into executable
|
||||
machine code.
|
||||
|
||||
*This is a work in progress that is not yet functional.*
|
||||
|
||||
.. image:: https://readthedocs.org/projects/cretonne/badge/?version=latest
|
||||
:target: https://cretonne.readthedocs.io/en/latest/?badge=latest
|
||||
:alt: Documentation Status
|
||||
|
||||
.. image:: https://travis-ci.org/Cretonne/cretonne.svg?branch=master
|
||||
:target: https://travis-ci.org/Cretonne/cretonne
|
||||
.. image:: https://travis-ci.org/cretonne/cretonne.svg?branch=master
|
||||
:target: https://travis-ci.org/cretonne/cretonne
|
||||
:alt: Build Status
|
||||
|
||||
.. image:: https://badges.gitter.im/Cretonne/cretonne.png
|
||||
:target: https://gitter.im/Cretonne/Lobby/~chat
|
||||
.. image:: https://badges.gitter.im/cretonne/cretonne.png
|
||||
:target: https://gitter.im/cretonne/Lobby/~chat
|
||||
:alt: Gitter chat
|
||||
|
||||
For more information, see `the documentation
|
||||
<https://cretonne.readthedocs.io/en/latest/?badge=latest>`_.
|
||||
|
||||
Status
|
||||
------
|
||||
|
||||
Cretonne currently supports enough functionality to run a wide variety of
|
||||
programs, including all the functionality needed to execute WebAssembly MVP
|
||||
functions, although it needs to be used within an external WebAssembly
|
||||
embedding to be part of a complete WebAssembly implementation.
|
||||
|
||||
The x86-64 backend is currently the most complete and stable; other
|
||||
architectures are in various stages of development. Cretonne currently supports
|
||||
the System V AMD64 ABI calling convention used on many platforms, but does not
|
||||
yet support the Windows x64 calling convention. The performance of code
|
||||
produced by Cretonne is not yet impressive, though we have plans to fix that.
|
||||
|
||||
The core codegen crates have minimal dependencies, and do not require any host
|
||||
floating-point support. Support for `no_std` mode in the core codegen crates is
|
||||
`in development <https://github.com/cretonne/cretonne/tree/no_std>`_.
|
||||
|
||||
Cretonne does not yet perform mitigations for Spectre or related security
|
||||
issues, though it may do so in the future. It does not currently make any
|
||||
security-relevant instruction timing guarantees. It has seen a fair amount
|
||||
of testing and fuzzing, although more work is needed before it would be
|
||||
ready for a production use case.
|
||||
|
||||
Cretonne's APIs are not yet stable.
|
||||
|
||||
Cretonne currently supports Rust 1.22.1 and later. We intend to always support
|
||||
the latest *stable* Rust. And, we currently support the version of Rust in the
|
||||
latest Ubuntu LTS, although whether we will always do so is not yet determined.
|
||||
Cretonne requires Python 2.7 or Python 3 to build.
|
||||
|
||||
Planned uses
|
||||
------------
|
||||
|
||||
|
||||
1
cranelift/.gitignore
vendored
1
cranelift/.gitignore
vendored
@@ -10,3 +10,4 @@ Cargo.lock
|
||||
cretonne.dbg*
|
||||
.mypy_cache
|
||||
rusty-tags.*
|
||||
docs/_build
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
[package]
|
||||
name = "cretonne-tools"
|
||||
authors = ["The Cretonne Project Developers"]
|
||||
version = "0.4.1"
|
||||
description = "Binaries for testing the Cretonne library"
|
||||
version = "0.5.0"
|
||||
description = "Binaries for testing the Cretonne libraries"
|
||||
license = "Apache-2.0"
|
||||
documentation = "https://cretonne.readthedocs.io/"
|
||||
repository = "https://github.com/Cretonne/cretonne"
|
||||
repository = "https://github.com/cretonne/cretonne"
|
||||
publish = false
|
||||
|
||||
[[bin]]
|
||||
@@ -13,12 +13,16 @@ name = "cton-util"
|
||||
path = "src/cton-util.rs"
|
||||
|
||||
[dependencies]
|
||||
cretonne = { path = "lib/cretonne", version = "0.4.1" }
|
||||
cretonne-reader = { path = "lib/reader", version = "0.4.1" }
|
||||
cretonne-frontend = { path = "lib/frontend", version = "0.4.1" }
|
||||
cretonne-wasm = { path = "lib/wasm", version = "0.4.1" }
|
||||
cretonne-native = { path = "lib/native", version = "0.4.1" }
|
||||
cretonne-filetests = { path = "lib/filetests", version = "0.4.1" }
|
||||
cretonne-codegen = { path = "lib/codegen", version = "0.5.0" }
|
||||
cretonne-reader = { path = "lib/reader", version = "0.5.0" }
|
||||
cretonne-frontend = { path = "lib/frontend", version = "0.5.0" }
|
||||
cretonne-wasm = { path = "lib/wasm", version = "0.5.0" }
|
||||
cretonne-native = { path = "lib/native", version = "0.5.0" }
|
||||
cretonne-filetests = { path = "lib/filetests", version = "0.5.0" }
|
||||
cretonne-module = { path = "lib/module", version = "0.5.0" }
|
||||
cretonne-faerie = { path = "lib/faerie", version = "0.5.0" }
|
||||
cretonne-simplejit = { path = "lib/simplejit", version = "0.5.0" }
|
||||
cretonne = { path = "lib/umbrella", version = "0.5.0" }
|
||||
filecheck = "0.2.1"
|
||||
docopt = "0.8.0"
|
||||
serde = "1.0.8"
|
||||
@@ -30,7 +34,7 @@ term = "0.5.1"
|
||||
|
||||
# Enable debug assertions and parallel compilation when building cretonne-tools
|
||||
# since they are for testing and development mostly. This doesn't affect the
|
||||
# flags used to build the Cretonne crate when used as a dependency.
|
||||
# flags used to build the cretonne-* crates when used as a dependency.
|
||||
[profile.release]
|
||||
opt-level = 2
|
||||
debug-assertions = true
|
||||
|
||||
@@ -14,7 +14,7 @@ help:
|
||||
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
||||
|
||||
autohtml: html
|
||||
$(SPHINXABUILD) -z ../lib/cretonne/meta --ignore '.*' -b html -E $(ALLSPHINXOPTS) $(BUILDDIR)/html
|
||||
$(SPHINXABUILD) -z ../lib/codegen/meta --ignore '.*' -b html -E $(ALLSPHINXOPTS) $(BUILDDIR)/html
|
||||
|
||||
.PHONY: help Makefile
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
test verifier
|
||||
|
||||
function %gcd(i32 uext, i32 uext) -> i32 uext system_v {
|
||||
fn1 = function %divmod(i32 uext, i32 uext) -> i32 uext, i32 uext
|
||||
fn1 = %divmod(i32 uext, i32 uext) -> i32 uext, i32 uext
|
||||
|
||||
ebb1(v1: i32, v2: i32):
|
||||
brz v2, ebb2
|
||||
|
||||
@@ -6,8 +6,8 @@ Cretonne compared to LLVM
|
||||
a set of C++ libraries. It can be used to build both JIT compilers and static
|
||||
compilers like `Clang <https://clang.llvm.org>`_, and it is deservedly very
|
||||
popular. `Chris Lattner's chapter about LLVM
|
||||
<http://www.aosabook.org/en/llvm.html>`_ in the `Architecture of Open Source
|
||||
Applications <http://aosabook.org/en/index.html>`_ book gives an excellent
|
||||
<https://www.aosabook.org/en/llvm.html>`_ in the `Architecture of Open Source
|
||||
Applications <https://aosabook.org/en/index.html>`_ book gives an excellent
|
||||
overview of the architecture and design of LLVM.
|
||||
|
||||
Cretonne and LLVM are superficially similar projects, so it is worth
|
||||
@@ -174,7 +174,7 @@ is emitted, there are opcodes for every native instruction that can be
|
||||
generated. There is a lot of overlap between different ISAs, so for example the
|
||||
:cton:inst:`iadd_imm` instruction is used by every ISA that can add an
|
||||
immediate integer to a register. A simple RISC ISA like RISC-V can be defined
|
||||
with only shared instructions, while an Intel ISA needs a number of specific
|
||||
with only shared instructions, while x86 needs a number of specific
|
||||
instructions to model addressing modes.
|
||||
|
||||
Undefined behavior
|
||||
|
||||
@@ -23,7 +23,7 @@ sys.path.insert(0, os.path.abspath('.'))
|
||||
|
||||
# Also add the meta directory to sys.path so autodoc can find the Cretonne meta
|
||||
# language definitions.
|
||||
sys.path.insert(0, os.path.abspath('../lib/cretonne/meta'))
|
||||
sys.path.insert(0, os.path.abspath('../lib/codegen/meta'))
|
||||
|
||||
# -- General configuration ------------------------------------------------
|
||||
|
||||
|
||||
@@ -48,8 +48,7 @@ A ``.cton`` file consists of a sequence of independent function definitions:
|
||||
|
||||
.. productionlist::
|
||||
function_list : { function }
|
||||
function : function_spec "{" preamble function_body "}"
|
||||
function_spec : "function" function_name signature
|
||||
function : "function" function_name signature "{" preamble function_body "}"
|
||||
preamble : { preamble_decl }
|
||||
function_body : { extended_basic_block }
|
||||
|
||||
@@ -75,7 +74,7 @@ SSA values: In the entry block, ``v4`` is the initial value. In the loop block
|
||||
variable during each iteration. Finally, ``v12`` is computed as the induction
|
||||
variable value for the next iteration.
|
||||
|
||||
The `cton_frontend` crate contains utilities for translating from programs
|
||||
The `cretonne_frontend` crate contains utilities for translating from programs
|
||||
containing multiple assignments to the same variables into SSA form for
|
||||
Cretonne :term:`IR`.
|
||||
|
||||
@@ -409,10 +408,14 @@ compilers.
|
||||
Functions that are called directly must be declared in the :term:`function
|
||||
preamble`:
|
||||
|
||||
.. inst:: FN = function NAME signature
|
||||
.. inst:: FN = [colocated] NAME signature
|
||||
|
||||
Declare a function so it can be called directly.
|
||||
|
||||
If the colocated keyword is present, the symbol's definition will be
|
||||
defined along with the current function, such that it can use more
|
||||
efficient addressing.
|
||||
|
||||
:arg NAME: Name of the function, passed to the linker for resolution.
|
||||
:arg signature: Function signature. See below.
|
||||
:result FN: A function identifier that can be used with :inst:`call`.
|
||||
@@ -570,13 +573,17 @@ runtime data structures.
|
||||
variable.
|
||||
:result GV: Global variable.
|
||||
|
||||
.. inst:: GV = globalsym name
|
||||
.. inst:: GV = [colocated] globalsym name
|
||||
|
||||
Declare a global variable at a symbolic address.
|
||||
|
||||
The address of GV is symbolic and will be assigned a relocation, so that
|
||||
it can be resolved by a later linking phase.
|
||||
|
||||
If the colocated keyword is present, the symbol's definition will be
|
||||
defined along with the current function, such that it can use more
|
||||
efficient addressing.
|
||||
|
||||
:arg name: External name.
|
||||
:result GV: Global variable.
|
||||
|
||||
@@ -998,20 +1005,20 @@ ISA-specific instructions
|
||||
Target ISAs can define supplemental instructions that do not make sense to
|
||||
support generally.
|
||||
|
||||
Intel
|
||||
x86
|
||||
-----
|
||||
|
||||
Instructions that can only be used by the Intel target ISA.
|
||||
Instructions that can only be used by the x86 target ISA.
|
||||
|
||||
.. autoinst:: isa.intel.instructions.sdivmodx
|
||||
.. autoinst:: isa.intel.instructions.udivmodx
|
||||
.. autoinst:: isa.intel.instructions.cvtt2si
|
||||
.. autoinst:: isa.intel.instructions.fmin
|
||||
.. autoinst:: isa.intel.instructions.fmax
|
||||
.. autoinst:: isa.intel.instructions.bsf
|
||||
.. autoinst:: isa.intel.instructions.bsr
|
||||
.. autoinst:: isa.intel.instructions.push
|
||||
.. autoinst:: isa.intel.instructions.pop
|
||||
.. autoinst:: isa.x86.instructions.sdivmodx
|
||||
.. autoinst:: isa.x86.instructions.udivmodx
|
||||
.. autoinst:: isa.x86.instructions.cvtt2si
|
||||
.. autoinst:: isa.x86.instructions.fmin
|
||||
.. autoinst:: isa.x86.instructions.fmax
|
||||
.. autoinst:: isa.x86.instructions.bsf
|
||||
.. autoinst:: isa.x86.instructions.bsr
|
||||
.. autoinst:: isa.x86.instructions.push
|
||||
.. autoinst:: isa.x86.instructions.pop
|
||||
|
||||
Instruction groups
|
||||
==================
|
||||
@@ -1023,7 +1030,7 @@ group.
|
||||
|
||||
Target ISAs may define further instructions in their own instruction groups:
|
||||
|
||||
.. autoinstgroup:: isa.intel.instructions.GROUP
|
||||
.. autoinstgroup:: isa.x86.instructions.GROUP
|
||||
|
||||
Implementation limits
|
||||
=====================
|
||||
|
||||
@@ -11,7 +11,7 @@ domain specific language embedded in Python. This document describes the Python
|
||||
modules that form the embedded DSL.
|
||||
|
||||
The meta language descriptions are Python modules under the
|
||||
:file:`lib/cretonne/meta` directory. The descriptions are processed in two
|
||||
:file:`lib/codegen/meta` directory. The descriptions are processed in two
|
||||
steps:
|
||||
|
||||
1. The Python modules are imported. This has the effect of building static data
|
||||
@@ -23,8 +23,8 @@ steps:
|
||||
constant tables.
|
||||
|
||||
The main driver for this source code generation process is the
|
||||
:file:`lib/cretonne/meta/build.py` script which is invoked as part of the build
|
||||
process if anything in the :file:`lib/cretonne/meta` directory has changed
|
||||
:file:`lib/codegen/meta/build.py` script which is invoked as part of the build
|
||||
process if anything in the :file:`lib/codegen/meta` directory has changed
|
||||
since the last build.
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ of code generation. Each setting is defined in the meta language so a compact
|
||||
and consistent Rust representation can be generated. Shared settings are defined
|
||||
in the :mod:`base.settings` module. Some settings are specific to a target ISA,
|
||||
and defined in a :file:`settings.py` module under the appropriate
|
||||
:file:`lib/cretonne/meta/isa/*` directory.
|
||||
:file:`lib/codegen/meta/isa/*` directory.
|
||||
|
||||
Settings can take boolean on/off values, small numbers, or explicitly enumerated
|
||||
symbolic values. Each type is represented by a sub-class of :class:`Setting`:
|
||||
@@ -400,7 +400,7 @@ Fixed register operands
|
||||
-----------------------
|
||||
|
||||
Some instructions use hard-coded input and output registers for some value
|
||||
operands. An example is the ``pblendvb`` Intel SSE instruction which takes one
|
||||
operands. An example is the ``pblendvb`` x86 SSE instruction which takes one
|
||||
of its three value operands in the hard-coded ``%xmm0`` register::
|
||||
|
||||
XMM0 = FPR[0]
|
||||
@@ -433,13 +433,13 @@ architectures. Each ISA is represented by a :py:class:`cdsl.isa.TargetISA` insta
|
||||
.. autoclass:: TargetISA
|
||||
|
||||
The definitions for each supported target live in a package under
|
||||
:file:`lib/cretonne/meta/isa`.
|
||||
:file:`lib/codegen/meta/isa`.
|
||||
|
||||
.. automodule:: isa
|
||||
:members:
|
||||
|
||||
.. automodule:: isa.riscv
|
||||
.. automodule:: isa.intel
|
||||
.. automodule:: isa.x86
|
||||
.. automodule:: isa.arm32
|
||||
.. automodule:: isa.arm64
|
||||
|
||||
|
||||
@@ -79,7 +79,7 @@ Different register banks
|
||||
|
||||
Instructions with fixed operands
|
||||
Some instructions use a fixed register for an operand. This happens on the
|
||||
Intel ISAs:
|
||||
x86 ISAs:
|
||||
|
||||
- Dynamic shift and rotate instructions take the shift amount in CL.
|
||||
- Division instructions use RAX and RDX for both input and output operands.
|
||||
@@ -109,7 +109,7 @@ ABI boundaries
|
||||
Aliasing registers
|
||||
Different registers sometimes share the same bits in the register bank.
|
||||
This can make it difficult to measure register pressure. For example, the
|
||||
Intel registers RAX, EAX, AX, AL, and AH overlap.
|
||||
x86 registers RAX, EAX, AX, AL, and AH overlap.
|
||||
|
||||
If only one of the aliasing registers can be used at a time, the aliasing
|
||||
doesn't cause problems since the registers can simply be counted as one
|
||||
|
||||
@@ -51,7 +51,7 @@ tested::
|
||||
//!
|
||||
//! # Example
|
||||
//! ```
|
||||
//! use cretonne::settings::{self, Configurable};
|
||||
//! use cretonne_codegen::settings::{self, Configurable};
|
||||
//!
|
||||
//! let mut b = settings::builder();
|
||||
//! b.set("opt_level", "fastest");
|
||||
@@ -73,9 +73,9 @@ test.
|
||||
|
||||
These tests are usually found in the :file:`tests` top-level directory where
|
||||
they have access to all the crates in the Cretonne repository. The
|
||||
:file:`lib/cretonne` and :file:`lib/reader` crates have no external
|
||||
:file:`lib/codegen` and :file:`lib/reader` crates have no external
|
||||
dependencies, which can make testing tedious. Integration tests that don't need
|
||||
to depend on other crates can be placed in :file:`lib/cretonne/tests` and
|
||||
to depend on other crates can be placed in :file:`lib/codegen/tests` and
|
||||
:file:`lib/reader/tests`.
|
||||
|
||||
File tests
|
||||
@@ -109,7 +109,7 @@ header:
|
||||
isa_spec : "isa" isa_name { `option` } "\n"
|
||||
|
||||
The options given on the ``isa`` line modify the ISA-specific settings defined in
|
||||
:file:`lib/cretonne/meta/isa/*/settings.py`.
|
||||
:file:`lib/codegen/meta/isa/*/settings.py`.
|
||||
|
||||
All types of tests allow shared Cretonne settings to be modified:
|
||||
|
||||
@@ -119,7 +119,7 @@ All types of tests allow shared Cretonne settings to be modified:
|
||||
option : flag | setting "=" value
|
||||
|
||||
The shared settings available for all target ISAs are defined in
|
||||
:file:`lib/cretonne/meta/base/settings.py`.
|
||||
:file:`lib/codegen/meta/base/settings.py`.
|
||||
|
||||
The ``set`` lines apply settings cumulatively::
|
||||
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
; binary emission of 64-bit code.
|
||||
test binemit
|
||||
set is_64bit
|
||||
set is_compressed
|
||||
set is_pic
|
||||
isa intel haswell
|
||||
|
||||
; The binary encodings can be verified with the command:
|
||||
;
|
||||
; sed -ne 's/^ *; asm: *//p' filetests/isa/intel/binary64-pic.cton | llvm-mc -show-encoding -triple=x86_64
|
||||
;
|
||||
|
||||
; Tests for i64 instructions.
|
||||
function %I64() {
|
||||
sig0 = ()
|
||||
fn0 = function %foo()
|
||||
|
||||
gv0 = globalsym %some_gv
|
||||
|
||||
; Use incoming_arg stack slots because they won't be relocated by the frame
|
||||
; layout.
|
||||
ss0 = incoming_arg 8, offset 0
|
||||
ss1 = incoming_arg 1024, offset -1024
|
||||
ss2 = incoming_arg 1024, offset -2048
|
||||
ss3 = incoming_arg 8, offset -2056
|
||||
|
||||
ebb0:
|
||||
|
||||
; asm: call foo@PLT
|
||||
call fn0() ; bin: e8 PLTRel4(%foo-4) 00000000
|
||||
|
||||
; asm: mov 0x0(%rip), %rax
|
||||
[-,%rax] v0 = func_addr.i64 fn0 ; bin: 48 8b 05 GOTPCRel4(%foo-4) 00000000
|
||||
; asm: mov 0x0(%rip), %rsi
|
||||
[-,%rsi] v1 = func_addr.i64 fn0 ; bin: 48 8b 35 GOTPCRel4(%foo-4) 00000000
|
||||
; asm: mov 0x0(%rip), %r10
|
||||
[-,%r10] v2 = func_addr.i64 fn0 ; bin: 4c 8b 15 GOTPCRel4(%foo-4) 00000000
|
||||
|
||||
; asm: call *%rax
|
||||
call_indirect sig0, v0() ; bin: ff d0
|
||||
; asm: call *%rsi
|
||||
call_indirect sig0, v1() ; bin: ff d6
|
||||
; asm: call *%r10
|
||||
call_indirect sig0, v2() ; bin: 41 ff d2
|
||||
|
||||
; asm: mov 0x0(%rip), %rcx
|
||||
[-,%rcx] v3 = globalsym_addr.i64 gv0 ; bin: 48 8b 0d GOTPCRel4(%some_gv-4) 00000000
|
||||
; asm: mov 0x0(%rip), %rsi
|
||||
[-,%rsi] v4 = globalsym_addr.i64 gv0 ; bin: 48 8b 35 GOTPCRel4(%some_gv-4) 00000000
|
||||
; asm: mov 0x0(%rip), %r10
|
||||
[-,%r10] v5 = globalsym_addr.i64 gv0 ; bin: 4c 8b 15 GOTPCRel4(%some_gv-4) 00000000
|
||||
|
||||
return
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
test compile
|
||||
set is_64bit
|
||||
set is_compressed
|
||||
isa intel haswell
|
||||
|
||||
function %foo() {
|
||||
ss0 = explicit_slot 168
|
||||
ebb0:
|
||||
return
|
||||
}
|
||||
|
||||
; check: function %foo(i64 fp [%rbp], i64 csr [%rbx], i64 csr [%r12], i64 csr [%r13], i64 csr [%r14], i64 csr [%r15]) -> i64 fp [%rbp], i64 csr [%rbx], i64 csr [%r12], i64 csr [%r13], i64 csr [%r14], i64 csr [%r15] system_v {
|
||||
; nextln: ss0 = explicit_slot 168, offset -224
|
||||
; nextln: ss1 = incoming_arg 56, offset -56
|
||||
; check: ebb0(v0: i64 [%rbp], v1: i64 [%rbx], v2: i64 [%r12], v3: i64 [%r13], v4: i64 [%r14], v5: i64 [%r15]):
|
||||
; nextln: x86_push v0
|
||||
; nextln: copy_special %rsp -> %rbp
|
||||
; nextln: x86_push v1
|
||||
; nextln: x86_push v2
|
||||
; nextln: x86_push v3
|
||||
; nextln: x86_push v4
|
||||
; nextln: x86_push v5
|
||||
; nextln: adjust_sp_imm -168
|
||||
; nextln: adjust_sp_imm 168
|
||||
; nextln: v11 = x86_pop.i64
|
||||
; nextln: v10 = x86_pop.i64
|
||||
; nextln: v9 = x86_pop.i64
|
||||
; nextln: v8 = x86_pop.i64
|
||||
; nextln: v7 = x86_pop.i64
|
||||
; nextln: v6 = x86_pop.i64
|
||||
; nextln: return v6, v7, v8, v9, v10, v11
|
||||
; nextln: }
|
||||
@@ -4,7 +4,7 @@ isa riscv
|
||||
|
||||
function %RV32I(i32 link [%x1]) -> i32 link [%x1] {
|
||||
sig0 = ()
|
||||
fn0 = function %foo()
|
||||
fn0 = %foo()
|
||||
|
||||
ebb0(v9999: i32):
|
||||
[-,%x10] v1 = iconst.i32 1
|
||||
|
||||
@@ -17,8 +17,8 @@ ebb0(v0: i64):
|
||||
}
|
||||
|
||||
function %split_call_arg(i32) {
|
||||
fn1 = function %foo(i64)
|
||||
fn2 = function %foo(i32, i64)
|
||||
fn1 = %foo(i64)
|
||||
fn2 = %foo(i32, i64)
|
||||
ebb0(v0: i32):
|
||||
v1 = uextend.i64 v0
|
||||
call fn1(v1)
|
||||
@@ -30,7 +30,7 @@ ebb0(v0: i32):
|
||||
}
|
||||
|
||||
function %split_ret_val() {
|
||||
fn1 = function %foo() -> i64
|
||||
fn1 = %foo() -> i64
|
||||
ebb0:
|
||||
v1 = call fn1()
|
||||
; check: ebb0($(link=$V): i32):
|
||||
@@ -45,7 +45,7 @@ ebb1(v10: i64):
|
||||
|
||||
; First return value is fine, second one is expanded.
|
||||
function %split_ret_val2() {
|
||||
fn1 = function %foo() -> i32, i64
|
||||
fn1 = %foo() -> i32, i64
|
||||
ebb0:
|
||||
v1, v2 = call fn1()
|
||||
; check: ebb0($(link=$V): i32):
|
||||
@@ -70,7 +70,7 @@ ebb0(v1: i8, v2: i8, v3: i8):
|
||||
|
||||
; Function produces single return value, still need to copy.
|
||||
function %ext_ret_val() {
|
||||
fn1 = function %foo() -> i8 sext
|
||||
fn1 = %foo() -> i8 sext
|
||||
ebb0:
|
||||
v1 = call fn1()
|
||||
; check: ebb0($V: i32):
|
||||
@@ -124,7 +124,7 @@ ebb0(v0: i32, v1: f32x2):
|
||||
; Call a function that takes arguments on the stack.
|
||||
function %stack_args(i32) {
|
||||
; check: $(ss0=$SS) = outgoing_arg 4
|
||||
fn1 = function %foo(i64, i64, i64, i64, i32)
|
||||
fn1 = %foo(i64, i64, i64, i64, i32)
|
||||
ebb0(v0: i32):
|
||||
v1 = iconst.i64 1
|
||||
call fn1(v1, v1, v1, v1, v0)
|
||||
|
||||
@@ -27,9 +27,9 @@ function %parse_encoding(i32 [%x5]) -> i32 [%x10] {
|
||||
; check: sig5 = () -> f32 [0] system_v
|
||||
|
||||
; function + signature
|
||||
fn0 = function %bar(i32 [%x10]) -> b1 [%x10] system_v
|
||||
fn0 = %bar(i32 [%x10]) -> b1 [%x10] system_v
|
||||
; check: sig6 = (i32 [%x10]) -> b1 [%x10] system_v
|
||||
; nextln: fn0 = sig6 %bar
|
||||
; nextln: fn0 = %bar sig6
|
||||
|
||||
ebb0(v0: i32):
|
||||
return v0
|
||||
|
||||
@@ -2,7 +2,7 @@ test verifier
|
||||
isa riscv
|
||||
|
||||
function %RV32I(i32 link [%x1]) -> i32 link [%x1] {
|
||||
fn0 = function %foo()
|
||||
fn0 = %foo()
|
||||
|
||||
ebb0(v9999: i32):
|
||||
; iconst.i32 needs legalizing, so it should throw a
|
||||
@@ -11,7 +11,7 @@ ebb0(v9999: i32):
|
||||
}
|
||||
|
||||
function %RV32I(i32 link [%x1]) -> i32 link [%x1] {
|
||||
fn0 = function %foo()
|
||||
fn0 = %foo()
|
||||
|
||||
ebb0(v9999: i32):
|
||||
v1 = iconst.i32 1
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
test compile
|
||||
set is_64bit=1
|
||||
isa intel haswell
|
||||
isa x86 haswell
|
||||
|
||||
function %foo(i64, i64, i64, i32) -> b1 system_v {
|
||||
ebb3(v0: i64, v1: i64, v2: i64, v3: i32):
|
||||
@@ -1,6 +1,6 @@
|
||||
; Test the legalization of function signatures.
|
||||
test legalizer
|
||||
isa intel
|
||||
isa x86
|
||||
|
||||
; regex: V=v\d+
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
; Test the legalization of function signatures.
|
||||
test legalizer
|
||||
set is_64bit
|
||||
isa intel
|
||||
isa x86
|
||||
|
||||
; regex: V=v\d+
|
||||
|
||||
@@ -21,7 +21,7 @@ ebb0:
|
||||
|
||||
function %pass_stack_int64(i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64 vmctx) spiderwasm {
|
||||
sig0 = (i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64 vmctx) spiderwasm
|
||||
fn0 = sig0 u0:0
|
||||
fn0 = u0:0 sig0
|
||||
|
||||
ebb0(v0: i64, v1: i64, v2: i64, v3: i64, v4: i64, v5: i64, v6: i64, v7: i64, v8: i64, v9: i64, v10: i64, v11: i64, v12: i64, v13: i64, v14: i64, v15: i64, v16: i64, v17: i64, v18: i64, v19: i64, v20: i64):
|
||||
call fn0(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20)
|
||||
@@ -2,17 +2,17 @@
|
||||
test binemit
|
||||
set is_compressed
|
||||
set allones_funcaddrs
|
||||
isa intel haswell
|
||||
isa x86 haswell
|
||||
|
||||
; The binary encodings can be verified with the command:
|
||||
;
|
||||
; sed -ne 's/^ *; asm: *//p' filetests/isa/intel/allones_funcaddrs32.cton | llvm-mc -show-encoding -triple=i386
|
||||
; sed -ne 's/^ *; asm: *//p' filetests/isa/x86/allones_funcaddrs32.cton | llvm-mc -show-encoding -triple=i386
|
||||
;
|
||||
|
||||
; Tests from binary32.cton affected by allones_funcaddrs.
|
||||
function %I32() {
|
||||
sig0 = ()
|
||||
fn0 = function %foo()
|
||||
fn0 = %foo()
|
||||
|
||||
ebb0:
|
||||
|
||||
@@ -3,17 +3,17 @@ test binemit
|
||||
set is_64bit
|
||||
set is_compressed
|
||||
set allones_funcaddrs
|
||||
isa intel haswell
|
||||
isa x86 haswell
|
||||
|
||||
; The binary encodings can be verified with the command:
|
||||
;
|
||||
; sed -ne 's/^ *; asm: *//p' filetests/isa/intel/allones_funcaddrs64.cton | llvm-mc -show-encoding -triple=x86_64
|
||||
; sed -ne 's/^ *; asm: *//p' filetests/isa/x86/allones_funcaddrs64.cton | llvm-mc -show-encoding -triple=x86_64
|
||||
;
|
||||
|
||||
; Tests from binary64.cton affected by allones_funcaddrs.
|
||||
function %I64() {
|
||||
sig0 = ()
|
||||
fn0 = function %foo()
|
||||
fn0 = %foo()
|
||||
|
||||
ebb0:
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
|
||||
test compile
|
||||
set is_64bit
|
||||
isa intel baseline
|
||||
isa x86 baseline
|
||||
|
||||
|
||||
; clz/ctz on 64 bit operands
|
||||
@@ -2,11 +2,11 @@
|
||||
test binemit
|
||||
set is_64bit
|
||||
set is_compressed
|
||||
isa intel baseline
|
||||
isa x86 baseline
|
||||
|
||||
; The binary encodings can be verified with the command:
|
||||
;
|
||||
; sed -ne 's/^ *; asm: *//p' filetests/isa/intel/baseline_clz_ctz_popcount_encoding.cton | llvm-mc -show-encoding -triple=x86_64
|
||||
; sed -ne 's/^ *; asm: *//p' filetests/isa/x86/baseline_clz_ctz_popcount_encoding.cton | llvm-mc -show-encoding -triple=x86_64
|
||||
;
|
||||
|
||||
function %Foo() {
|
||||
@@ -1,10 +1,10 @@
|
||||
; Binary emission of 32-bit floating point code.
|
||||
test binemit
|
||||
isa intel haswell
|
||||
isa x86 haswell
|
||||
|
||||
; The binary encodings can be verified with the command:
|
||||
;
|
||||
; sed -ne 's/^ *; asm: *//p' filetests/isa/intel/binary32-float.cton | llvm-mc -show-encoding -triple=i386
|
||||
; sed -ne 's/^ *; asm: *//p' filetests/isa/x86/binary32-float.cton | llvm-mc -show-encoding -triple=i386
|
||||
;
|
||||
|
||||
function %F32() {
|
||||
@@ -1,16 +1,16 @@
|
||||
; binary emission of x86-32 code.
|
||||
test binemit
|
||||
set is_compressed
|
||||
isa intel haswell
|
||||
isa x86 haswell
|
||||
|
||||
; The binary encodings can be verified with the command:
|
||||
;
|
||||
; sed -ne 's/^ *; asm: *//p' filetests/isa/intel/binary32.cton | llvm-mc -show-encoding -triple=i386
|
||||
; sed -ne 's/^ *; asm: *//p' filetests/isa/x86/binary32.cton | llvm-mc -show-encoding -triple=i386
|
||||
;
|
||||
|
||||
function %I32() {
|
||||
sig0 = ()
|
||||
fn0 = function %foo()
|
||||
fn0 = %foo()
|
||||
|
||||
gv0 = globalsym %some_gv
|
||||
|
||||
@@ -352,7 +352,7 @@ ebb0:
|
||||
[-,%rsi] v351 = bint.i32 v301 ; bin: 0f b6 f2
|
||||
|
||||
; asm: call foo
|
||||
call fn0() ; bin: e8 PCRel4(%foo) 00000000
|
||||
call fn0() ; bin: e8 PCRel4(%foo-4) 00000000
|
||||
|
||||
; asm: movl $0, %ecx
|
||||
[-,%rcx] v400 = func_addr.i32 fn0 ; bin: b9 Abs4(%foo) 00000000
|
||||
@@ -2,11 +2,11 @@
|
||||
test binemit
|
||||
set is_64bit
|
||||
set is_compressed
|
||||
isa intel haswell
|
||||
isa x86 haswell
|
||||
|
||||
; The binary encodings can be verified with the command:
|
||||
;
|
||||
; sed -ne 's/^ *; asm: *//p' filetests/isa/intel/binary64-float.cton | llvm-mc -show-encoding -triple=x86_64
|
||||
; sed -ne 's/^ *; asm: *//p' filetests/isa/x86/binary64-float.cton | llvm-mc -show-encoding -triple=x86_64
|
||||
;
|
||||
|
||||
function %F32() {
|
||||
84
cranelift/filetests/isa/x86/binary64-pic.cton
Normal file
84
cranelift/filetests/isa/x86/binary64-pic.cton
Normal file
@@ -0,0 +1,84 @@
|
||||
; binary emission of 64-bit code.
|
||||
test binemit
|
||||
set is_64bit
|
||||
set is_compressed
|
||||
set is_pic
|
||||
isa x86 haswell
|
||||
|
||||
; The binary encodings can be verified with the command:
|
||||
;
|
||||
; sed -ne 's/^ *; asm: *//p' filetests/isa/x86/binary64-pic.cton | llvm-mc -show-encoding -triple=x86_64
|
||||
;
|
||||
|
||||
; Tests for i64 instructions.
|
||||
function %I64() {
|
||||
sig0 = ()
|
||||
fn0 = %foo()
|
||||
fn1 = colocated %bar()
|
||||
|
||||
gv0 = globalsym %some_gv
|
||||
gv1 = globalsym colocated %some_gv
|
||||
|
||||
; Use incoming_arg stack slots because they won't be relocated by the frame
|
||||
; layout.
|
||||
ss0 = incoming_arg 8, offset 0
|
||||
ss1 = incoming_arg 1024, offset -1024
|
||||
ss2 = incoming_arg 1024, offset -2048
|
||||
ss3 = incoming_arg 8, offset -2056
|
||||
|
||||
ebb0:
|
||||
|
||||
; Colocated functions.
|
||||
|
||||
; asm: call foo
|
||||
call fn1() ; bin: e8 PCRel4(%bar-4) 00000000
|
||||
|
||||
; asm: lea 0x0(%rip), %rax
|
||||
[-,%rax] v0 = func_addr.i64 fn1 ; bin: 48 8d 05 PCRel4(%bar-4) 00000000
|
||||
; asm: lea 0x0(%rip), %rsi
|
||||
[-,%rsi] v1 = func_addr.i64 fn1 ; bin: 48 8d 35 PCRel4(%bar-4) 00000000
|
||||
; asm: lea 0x0(%rip), %r10
|
||||
[-,%r10] v2 = func_addr.i64 fn1 ; bin: 4c 8d 15 PCRel4(%bar-4) 00000000
|
||||
|
||||
; asm: call *%rax
|
||||
call_indirect sig0, v0() ; bin: ff d0
|
||||
; asm: call *%rsi
|
||||
call_indirect sig0, v1() ; bin: ff d6
|
||||
; asm: call *%r10
|
||||
call_indirect sig0, v2() ; bin: 41 ff d2
|
||||
|
||||
; Non-colocated functions.
|
||||
|
||||
; asm: call foo@PLT
|
||||
call fn0() ; bin: e8 PLTRel4(%foo-4) 00000000
|
||||
|
||||
; asm: mov 0x0(%rip), %rax
|
||||
[-,%rax] v100 = func_addr.i64 fn0 ; bin: 48 8b 05 GOTPCRel4(%foo-4) 00000000
|
||||
; asm: mov 0x0(%rip), %rsi
|
||||
[-,%rsi] v101 = func_addr.i64 fn0 ; bin: 48 8b 35 GOTPCRel4(%foo-4) 00000000
|
||||
; asm: mov 0x0(%rip), %r10
|
||||
[-,%r10] v102 = func_addr.i64 fn0 ; bin: 4c 8b 15 GOTPCRel4(%foo-4) 00000000
|
||||
|
||||
; asm: call *%rax
|
||||
call_indirect sig0, v100() ; bin: ff d0
|
||||
; asm: call *%rsi
|
||||
call_indirect sig0, v101() ; bin: ff d6
|
||||
; asm: call *%r10
|
||||
call_indirect sig0, v102() ; bin: 41 ff d2
|
||||
|
||||
; asm: mov 0x0(%rip), %rcx
|
||||
[-,%rcx] v3 = globalsym_addr.i64 gv0 ; bin: 48 8b 0d GOTPCRel4(%some_gv-4) 00000000
|
||||
; asm: mov 0x0(%rip), %rsi
|
||||
[-,%rsi] v4 = globalsym_addr.i64 gv0 ; bin: 48 8b 35 GOTPCRel4(%some_gv-4) 00000000
|
||||
; asm: mov 0x0(%rip), %r10
|
||||
[-,%r10] v5 = globalsym_addr.i64 gv0 ; bin: 4c 8b 15 GOTPCRel4(%some_gv-4) 00000000
|
||||
|
||||
; asm: lea 0x0(%rip), %rcx
|
||||
[-,%rcx] v6 = globalsym_addr.i64 gv1 ; bin: 48 8d 0d PCRel4(%some_gv-4) 00000000
|
||||
; asm: lea 0x0(%rip), %rsi
|
||||
[-,%rsi] v7 = globalsym_addr.i64 gv1 ; bin: 48 8d 35 PCRel4(%some_gv-4) 00000000
|
||||
; asm: lea 0x0(%rip), %r10
|
||||
[-,%r10] v8 = globalsym_addr.i64 gv1 ; bin: 4c 8d 15 PCRel4(%some_gv-4) 00000000
|
||||
|
||||
return
|
||||
}
|
||||
@@ -2,17 +2,18 @@
|
||||
test binemit
|
||||
set is_64bit
|
||||
set is_compressed
|
||||
isa intel haswell
|
||||
isa x86 haswell
|
||||
|
||||
; The binary encodings can be verified with the command:
|
||||
;
|
||||
; sed -ne 's/^ *; asm: *//p' filetests/isa/intel/binary64.cton | llvm-mc -show-encoding -triple=x86_64
|
||||
; sed -ne 's/^ *; asm: *//p' filetests/isa/x86/binary64.cton | llvm-mc -show-encoding -triple=x86_64
|
||||
;
|
||||
|
||||
; Tests for i64 instructions.
|
||||
function %I64() {
|
||||
sig0 = ()
|
||||
fn0 = function %foo()
|
||||
fn0 = %foo()
|
||||
fn1 = colocated %bar()
|
||||
|
||||
gv0 = globalsym %some_gv
|
||||
|
||||
@@ -473,15 +474,17 @@ ebb0:
|
||||
; asm: movzbq %dl, %rsi
|
||||
[-,%rsi] v351 = bint.i64 v301 ; bin: 0f b6 f2
|
||||
|
||||
; asm: call foo
|
||||
call fn0() ; bin: e8 PCRel4(%foo) 00000000
|
||||
; Colocated functions.
|
||||
|
||||
; asm: movabsq $0, %rcx
|
||||
[-,%rcx] v400 = func_addr.i64 fn0 ; bin: 48 b9 Abs8(%foo) 0000000000000000
|
||||
; asm: movabsq $0, %rsi
|
||||
[-,%rsi] v401 = func_addr.i64 fn0 ; bin: 48 be Abs8(%foo) 0000000000000000
|
||||
; asm: movabsq $0, %r10
|
||||
[-,%r10] v402 = func_addr.i64 fn0 ; bin: 49 ba Abs8(%foo) 0000000000000000
|
||||
; asm: call bar
|
||||
; call fn1() ; bin: e8 PCRel4(%bar-4) 00000000
|
||||
|
||||
; asm: lea 0x0(%rip), %rcx
|
||||
[-,%rcx] v400 = func_addr.i64 fn1 ; bin: 48 8d 0d PCRel4(%bar-4) 00000000
|
||||
; asm: lea 0x0(%rip), %rsi
|
||||
[-,%rsi] v401 = func_addr.i64 fn1 ; bin: 48 8d 35 PCRel4(%bar-4) 00000000
|
||||
; asm: lea 0x0(%rip), %r10
|
||||
[-,%r10] v402 = func_addr.i64 fn1 ; bin: 4c 8d 15 PCRel4(%bar-4) 00000000
|
||||
|
||||
; asm: call *%rcx
|
||||
call_indirect sig0, v400() ; bin: ff d1
|
||||
@@ -490,6 +493,22 @@ ebb0:
|
||||
; asm: call *%r10
|
||||
call_indirect sig0, v402() ; bin: 41 ff d2
|
||||
|
||||
; Non-colocated functions. Note that there is no non-colocated non-PIC call.
|
||||
|
||||
; asm: movabsq $0, %rcx
|
||||
[-,%rcx] v410 = func_addr.i64 fn0 ; bin: 48 b9 Abs8(%foo) 0000000000000000
|
||||
; asm: movabsq $0, %rsi
|
||||
[-,%rsi] v411 = func_addr.i64 fn0 ; bin: 48 be Abs8(%foo) 0000000000000000
|
||||
; asm: movabsq $0, %r10
|
||||
[-,%r10] v412 = func_addr.i64 fn0 ; bin: 49 ba Abs8(%foo) 0000000000000000
|
||||
|
||||
; asm: call *%rcx
|
||||
call_indirect sig0, v410() ; bin: ff d1
|
||||
; asm: call *%rsi
|
||||
call_indirect sig0, v411() ; bin: ff d6
|
||||
; asm: call *%r10
|
||||
call_indirect sig0, v412() ; bin: 41 ff d2
|
||||
|
||||
; asm: movabsq $-1, %rcx
|
||||
[-,%rcx] v450 = globalsym_addr.i64 gv0 ; bin: 48 b9 Abs8(%some_gv) 0000000000000000
|
||||
; asm: movabsq $-1, %rsi
|
||||
@@ -551,9 +570,9 @@ ebb0:
|
||||
[-,%rsi] v517 = sshr_imm v2, 32 ; bin: 48 c1 fe 20
|
||||
; asm: sarq $33, %r8
|
||||
[-,%r8] v518 = sshr_imm v4, 33 ; bin: 49 c1 f8 21
|
||||
; asm: shrl $62, %rsi
|
||||
; asm: shrq $62, %rsi
|
||||
[-,%rsi] v519 = ushr_imm v2, 62 ; bin: 48 c1 ee 3e
|
||||
; asm: shrl $63, %r8
|
||||
; asm: shrq $63, %r8
|
||||
[-,%r8] v520 = ushr_imm v4, 63 ; bin: 49 c1 e8 3f
|
||||
|
||||
|
||||
@@ -710,7 +729,7 @@ ebb0:
|
||||
; be done by an instruction shrinking pass.
|
||||
function %I32() {
|
||||
sig0 = ()
|
||||
fn0 = function %foo()
|
||||
fn0 = %foo()
|
||||
|
||||
ss0 = incoming_arg 8, offset 0
|
||||
ss1 = incoming_arg 1024, offset -1024
|
||||
@@ -1043,7 +1062,7 @@ ebb0:
|
||||
; asm: setl %bl
|
||||
[-,%rbx] v320 = icmp_imm slt v1, 37 ; bin: 83 f9 25 0f 9c c3
|
||||
|
||||
; asm: cmpq $100000, %ecx
|
||||
; asm: cmpl $100000, %ecx
|
||||
; asm: setl %bl
|
||||
[-,%rbx] v321 = icmp_imm slt v1, 100000 ; bin: 81 f9 000186a0 0f 9c c3
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
; Test the custom legalizations.
|
||||
test legalizer
|
||||
isa intel
|
||||
isa x86
|
||||
set is_64bit
|
||||
isa intel
|
||||
isa x86
|
||||
|
||||
; regex: V=v\d+
|
||||
; regex: EBB=ebb\d+
|
||||
@@ -3,7 +3,7 @@ test legalizer
|
||||
set is_64bit
|
||||
; See also legalize-div.cton.
|
||||
set avoid_div_traps=1
|
||||
isa intel
|
||||
isa x86
|
||||
|
||||
; regex: V=v\d+
|
||||
; regex: EBB=ebb\d+
|
||||
@@ -3,7 +3,7 @@ test legalizer
|
||||
set is_64bit
|
||||
; See also legalize-div-traps.cton.
|
||||
set avoid_div_traps=0
|
||||
isa intel
|
||||
isa x86
|
||||
|
||||
; regex: V=v\d+
|
||||
; regex: EBB=ebb\d+
|
||||
@@ -2,7 +2,8 @@ test legalizer
|
||||
|
||||
; Pre-SSE 4.1, we need to use runtime library calls for floating point rounding operations.
|
||||
set is_64bit
|
||||
isa intel
|
||||
set is_pic
|
||||
isa x86
|
||||
|
||||
function %floor(f32) -> f32 {
|
||||
ebb0(v0: f32):
|
||||
@@ -11,5 +12,5 @@ ebb0(v0: f32):
|
||||
}
|
||||
; check: function %floor(f32 [%xmm0]) -> f32 [%xmm0] system_v {
|
||||
; check: sig0 = (f32) -> f32 system_v
|
||||
; check: fn0 = sig0 %FloorF32
|
||||
; check: fn0 = %FloorF32 sig0
|
||||
; check: v1 = call fn0(v0)
|
||||
@@ -1,7 +1,7 @@
|
||||
; Test the legalization of memory objects.
|
||||
test legalizer
|
||||
set is_64bit
|
||||
isa intel
|
||||
isa x86
|
||||
|
||||
; regex: V=v\d+
|
||||
; regex: EBB=ebb\d+
|
||||
@@ -1,7 +1,7 @@
|
||||
|
||||
test compile
|
||||
set is_64bit
|
||||
isa intel baseline
|
||||
isa x86 baseline
|
||||
|
||||
; umulhi/smulhi on 64 bit operands
|
||||
|
||||
231
cranelift/filetests/isa/x86/prologue-epilogue.cton
Normal file
231
cranelift/filetests/isa/x86/prologue-epilogue.cton
Normal file
@@ -0,0 +1,231 @@
|
||||
test compile
|
||||
set is_64bit
|
||||
set is_compressed
|
||||
set is_pic
|
||||
isa x86 haswell
|
||||
|
||||
; An empty function.
|
||||
|
||||
function %empty() {
|
||||
ebb0:
|
||||
return
|
||||
}
|
||||
|
||||
; check: function %empty(i64 fp [%rbp]) -> i64 fp [%rbp] system_v {
|
||||
; nextln: ss0 = incoming_arg 16, offset -16
|
||||
; nextln:
|
||||
; nextln: ebb0(v0: i64 [%rbp]):
|
||||
; nextln: x86_push v0
|
||||
; nextln: copy_special %rsp -> %rbp
|
||||
; nextln: v1 = x86_pop.i64
|
||||
; nextln: return v1
|
||||
; nextln: }
|
||||
|
||||
; A function with a single stack slot.
|
||||
|
||||
function %one_stack_slot() {
|
||||
ss0 = explicit_slot 168
|
||||
ebb0:
|
||||
return
|
||||
}
|
||||
|
||||
; check: function %one_stack_slot(i64 fp [%rbp]) -> i64 fp [%rbp] system_v {
|
||||
; nextln: ss0 = explicit_slot 168, offset -184
|
||||
; nextln: ss1 = incoming_arg 16, offset -16
|
||||
; nextln:
|
||||
; nextln: ebb0(v0: i64 [%rbp]):
|
||||
; nextln: x86_push v0
|
||||
; nextln: copy_special %rsp -> %rbp
|
||||
; nextln: adjust_sp_imm -176
|
||||
; nextln: adjust_sp_imm 176
|
||||
; nextln: v1 = x86_pop.i64
|
||||
; nextln: return v1
|
||||
; nextln: }
|
||||
|
||||
; A function performing a call.
|
||||
|
||||
function %call() {
|
||||
fn0 = %foo()
|
||||
|
||||
ebb0:
|
||||
call fn0()
|
||||
return
|
||||
}
|
||||
|
||||
; check: function %call(i64 fp [%rbp]) -> i64 fp [%rbp] system_v {
|
||||
; nextln: ss0 = incoming_arg 16, offset -16
|
||||
; nextln: sig0 = () system_v
|
||||
; nextln: fn0 = %foo sig0
|
||||
; nextln:
|
||||
; nextln: ebb0(v0: i64 [%rbp]):
|
||||
; nextln: x86_push v0
|
||||
; nextln: copy_special %rsp -> %rbp
|
||||
; nextln: call fn0()
|
||||
; nextln: v1 = x86_pop.i64
|
||||
; nextln: return v1
|
||||
; nextln: }
|
||||
|
||||
; A function that uses a lot of registers but doesn't quite need to spill.
|
||||
|
||||
function %no_spill(i64, i64) {
|
||||
ebb0(v0: i64, v1: i64):
|
||||
v2 = load.i32 v0+0
|
||||
v3 = load.i32 v0+8
|
||||
v4 = load.i32 v0+16
|
||||
v5 = load.i32 v0+24
|
||||
v6 = load.i32 v0+32
|
||||
v7 = load.i32 v0+40
|
||||
v8 = load.i32 v0+48
|
||||
v9 = load.i32 v0+56
|
||||
v10 = load.i32 v0+64
|
||||
v11 = load.i32 v0+72
|
||||
v12 = load.i32 v0+80
|
||||
v13 = load.i32 v0+88
|
||||
v14 = load.i32 v0+96
|
||||
store.i32 v2, v1+0
|
||||
store.i32 v3, v1+8
|
||||
store.i32 v4, v1+16
|
||||
store.i32 v5, v1+24
|
||||
store.i32 v6, v1+32
|
||||
store.i32 v7, v1+40
|
||||
store.i32 v8, v1+48
|
||||
store.i32 v9, v1+56
|
||||
store.i32 v10, v1+64
|
||||
store.i32 v11, v1+72
|
||||
store.i32 v12, v1+80
|
||||
store.i32 v13, v1+88
|
||||
store.i32 v14, v1+96
|
||||
return
|
||||
}
|
||||
|
||||
; check: function %no_spill(i64 [%rdi], i64 [%rsi], i64 fp [%rbp], i64 csr [%rbx], i64 csr [%r12], i64 csr [%r13], i64 csr [%r14], i64 csr [%r15]) -> i64 fp [%rbp], i64 csr [%rbx], i64 csr [%r12], i64 csr [%r13], i64 csr [%r14], i64 csr [%r15] system_v {
|
||||
; nextln: ss0 = incoming_arg 56, offset -56
|
||||
; nextln:
|
||||
; nextln: ebb0(v0: i64 [%rdi], v1: i64 [%rsi], v15: i64 [%rbp], v16: i64 [%rbx], v17: i64 [%r12], v18: i64 [%r13], v19: i64 [%r14], v20: i64 [%r15]):
|
||||
; nextln: x86_push v15
|
||||
; nextln: copy_special %rsp -> %rbp
|
||||
; nextln: x86_push v16
|
||||
; nextln: x86_push v17
|
||||
; nextln: x86_push v18
|
||||
; nextln: x86_push v19
|
||||
; nextln: x86_push v20
|
||||
; nextln: adjust_sp_imm -8
|
||||
; nextln: v2 = load.i32 v0
|
||||
; nextln: v3 = load.i32 v0+8
|
||||
; nextln: v4 = load.i32 v0+16
|
||||
; nextln: v5 = load.i32 v0+24
|
||||
; nextln: v6 = load.i32 v0+32
|
||||
; nextln: v7 = load.i32 v0+40
|
||||
; nextln: v8 = load.i32 v0+48
|
||||
; nextln: v9 = load.i32 v0+56
|
||||
; nextln: v10 = load.i32 v0+64
|
||||
; nextln: v11 = load.i32 v0+72
|
||||
; nextln: v12 = load.i32 v0+80
|
||||
; nextln: v13 = load.i32 v0+88
|
||||
; nextln: v14 = load.i32 v0+96
|
||||
; nextln: store v2, v1
|
||||
; nextln: store v3, v1+8
|
||||
; nextln: store v4, v1+16
|
||||
; nextln: store v5, v1+24
|
||||
; nextln: store v6, v1+32
|
||||
; nextln: store v7, v1+40
|
||||
; nextln: store v8, v1+48
|
||||
; nextln: store v9, v1+56
|
||||
; nextln: store v10, v1+64
|
||||
; nextln: store v11, v1+72
|
||||
; nextln: store v12, v1+80
|
||||
; nextln: store v13, v1+88
|
||||
; nextln: store v14, v1+96
|
||||
; nextln: adjust_sp_imm 8
|
||||
; nextln: v26 = x86_pop.i64
|
||||
; nextln: v25 = x86_pop.i64
|
||||
; nextln: v24 = x86_pop.i64
|
||||
; nextln: v23 = x86_pop.i64
|
||||
; nextln: v22 = x86_pop.i64
|
||||
; nextln: v21 = x86_pop.i64
|
||||
; nextln: return v21, v22, v23, v24, v25, v26
|
||||
; nextln: }
|
||||
|
||||
; This function requires too many registers and must spill.
|
||||
|
||||
function %yes_spill(i64, i64) {
|
||||
ebb0(v0: i64, v1: i64):
|
||||
v2 = load.i32 v0+0
|
||||
v3 = load.i32 v0+8
|
||||
v4 = load.i32 v0+16
|
||||
v5 = load.i32 v0+24
|
||||
v6 = load.i32 v0+32
|
||||
v7 = load.i32 v0+40
|
||||
v8 = load.i32 v0+48
|
||||
v9 = load.i32 v0+56
|
||||
v10 = load.i32 v0+64
|
||||
v11 = load.i32 v0+72
|
||||
v12 = load.i32 v0+80
|
||||
v13 = load.i32 v0+88
|
||||
v14 = load.i32 v0+96
|
||||
v15 = load.i32 v0+104
|
||||
store.i32 v2, v1+0
|
||||
store.i32 v3, v1+8
|
||||
store.i32 v4, v1+16
|
||||
store.i32 v5, v1+24
|
||||
store.i32 v6, v1+32
|
||||
store.i32 v7, v1+40
|
||||
store.i32 v8, v1+48
|
||||
store.i32 v9, v1+56
|
||||
store.i32 v10, v1+64
|
||||
store.i32 v11, v1+72
|
||||
store.i32 v12, v1+80
|
||||
store.i32 v13, v1+88
|
||||
store.i32 v14, v1+96
|
||||
store.i32 v15, v1+104
|
||||
return
|
||||
}
|
||||
|
||||
; check: function %yes_spill(i64 [%rdi], i64 [%rsi], i64 fp [%rbp], i64 csr [%rbx], i64 csr [%r12], i64 csr [%r13], i64 csr [%r14], i64 csr [%r15]) -> i64 fp [%rbp], i64 csr [%rbx], i64 csr [%r12], i64 csr [%r13], i64 csr [%r14], i64 csr [%r15] system_v {
|
||||
; check: ss0 = spill_slot
|
||||
|
||||
; check: ebb0(v16: i64 [%rdi], v17: i64 [%rsi], v48: i64 [%rbp], v49: i64 [%rbx], v50: i64 [%r12], v51: i64 [%r13], v52: i64 [%r14], v53: i64 [%r15]):
|
||||
; nextln: x86_push v48
|
||||
; nextln: copy_special %rsp -> %rbp
|
||||
; nextln: x86_push v49
|
||||
; nextln: x86_push v50
|
||||
; nextln: x86_push v51
|
||||
; nextln: x86_push v52
|
||||
; nextln: x86_push v53
|
||||
; nextln: adjust_sp_imm
|
||||
|
||||
; check: spill
|
||||
|
||||
; check: fill
|
||||
|
||||
; check: adjust_sp_imm
|
||||
; nextln: v59 = x86_pop.i64
|
||||
; nextln: v58 = x86_pop.i64
|
||||
; nextln: v57 = x86_pop.i64
|
||||
; nextln: v56 = x86_pop.i64
|
||||
; nextln: v55 = x86_pop.i64
|
||||
; nextln: v54 = x86_pop.i64
|
||||
; nextln: return v54, v55, v56, v57, v58, v59
|
||||
; nextln: }
|
||||
|
||||
; A function which uses diverted registers.
|
||||
|
||||
function %divert(i32) -> i32 system_v {
|
||||
ebb0(v0: i32):
|
||||
v2 = iconst.i32 0
|
||||
v3 = iconst.i32 1
|
||||
jump ebb3(v0, v3, v2)
|
||||
|
||||
ebb3(v4: i32, v5: i32, v6: i32):
|
||||
brz v4, ebb4
|
||||
v7 = iadd v5, v6
|
||||
v8 = iadd_imm v4, -1
|
||||
jump ebb3(v8, v7, v5)
|
||||
|
||||
ebb4:
|
||||
return v5
|
||||
}
|
||||
|
||||
; check: function %divert
|
||||
; check: regmove v5, %rcx -> %rbx
|
||||
; check: [RexOp1popq#58,%rbx] v15 = x86_pop.i64
|
||||
@@ -26,22 +26,22 @@ ebb1:
|
||||
function %signatures() {
|
||||
sig10 = ()
|
||||
sig11 = (i32, f64) -> i32, b1 spiderwasm
|
||||
fn5 = sig11 %foo
|
||||
fn8 = function %bar(i32) -> b1
|
||||
fn5 = %foo sig11
|
||||
fn8 = %bar(i32) -> b1
|
||||
}
|
||||
; sameln: function %signatures() system_v {
|
||||
; check: sig10 = () system_v
|
||||
; check: sig11 = (i32, f64) -> i32, b1 spiderwasm
|
||||
; check: sig12 = (i32) -> b1 system_v
|
||||
; not: fn0
|
||||
; check: fn5 = sig11 %foo
|
||||
; check: fn8 = sig12 %bar
|
||||
; check: fn5 = %foo sig11
|
||||
; check: fn8 = %bar sig12
|
||||
; check: }
|
||||
|
||||
function %direct() {
|
||||
fn0 = function %none()
|
||||
fn1 = function %one() -> i32
|
||||
fn2 = function %two() -> i32, f32
|
||||
fn0 = %none()
|
||||
fn1 = %one() -> i32
|
||||
fn2 = %two() -> i32, f32
|
||||
|
||||
ebb0:
|
||||
call fn0()
|
||||
@@ -72,7 +72,7 @@ ebb0(v0: i64):
|
||||
|
||||
function %long_call() {
|
||||
sig0 = ()
|
||||
fn0 = sig0 %none
|
||||
fn0 = %none sig0
|
||||
|
||||
ebb0:
|
||||
v0 = func_addr.i32 fn0
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
test postopt
|
||||
isa intel
|
||||
isa x86
|
||||
|
||||
; Test that compare+branch sequences are folded effectively on x86.
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
test preopt
|
||||
isa intel baseline
|
||||
isa x86 baseline
|
||||
|
||||
; Cases where the denominator is created by an iconst
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
test preopt
|
||||
isa intel baseline
|
||||
isa x86 baseline
|
||||
|
||||
; -------- U32 --------
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
test preopt
|
||||
isa intel baseline
|
||||
isa x86 baseline
|
||||
|
||||
; -------- U32 --------
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
test preopt
|
||||
isa intel baseline
|
||||
isa x86 baseline
|
||||
|
||||
; -------- U32 --------
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
test preopt
|
||||
isa intel baseline
|
||||
isa x86 baseline
|
||||
|
||||
; -------- U32 --------
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
test preopt
|
||||
isa intel
|
||||
isa x86
|
||||
|
||||
function %iadd_imm(i32) -> i32 {
|
||||
ebb0(v0: i32):
|
||||
@@ -75,6 +75,6 @@ ebb0(v0: i32):
|
||||
; sameln: function %irsub_imm
|
||||
; nextln: ebb0(v0: i32):
|
||||
; nextln: v1 = iconst.i32 2
|
||||
; nextln: v2 = irsub_imm v1, 2
|
||||
; nextln: v2 = irsub_imm v0, 2
|
||||
; nextln: return v2
|
||||
; nextln: }
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
test regalloc
|
||||
set is_64bit
|
||||
isa intel haswell
|
||||
isa x86 haswell
|
||||
|
||||
function %value_aliases(i32, f32, i64 vmctx) spiderwasm {
|
||||
gv0 = vmctx
|
||||
|
||||
@@ -53,7 +53,7 @@ ebb1(v10: i32):
|
||||
|
||||
; Pass an EBB argument as a function argument.
|
||||
function %callebb(i32, i32) -> i32 {
|
||||
fn0 = function %foo(i32) -> i32
|
||||
fn0 = %foo(i32) -> i32
|
||||
|
||||
ebb0(v1: i32, v2: i32):
|
||||
brnz v1, ebb1(v1)
|
||||
@@ -66,7 +66,7 @@ ebb1(v10: i32):
|
||||
|
||||
; Pass an EBB argument as a jump argument.
|
||||
function %jumpebb(i32, i32) -> i32 {
|
||||
fn0 = function %foo(i32) -> i32
|
||||
fn0 = %foo(i32) -> i32
|
||||
|
||||
ebb0(v1: i32, v2: i32):
|
||||
brnz v1, ebb1(v1, v2)
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
test regalloc
|
||||
set is_64bit
|
||||
isa intel haswell
|
||||
isa x86 haswell
|
||||
|
||||
; Reported as https://github.com/Cretonne/cretonne/issues/207
|
||||
; Reported as https://github.com/cretonne/cretonne/issues/207
|
||||
;
|
||||
; The coalescer creates a virtual register with two interfering values.
|
||||
function %pr207(i64 vmctx, i32, i32) -> i32 system_v {
|
||||
@@ -11,9 +11,9 @@ function %pr207(i64 vmctx, i32, i32) -> i32 system_v {
|
||||
sig0 = (i64 vmctx, i32, i32) -> i32 system_v
|
||||
sig1 = (i64 vmctx, i32, i32, i32) -> i32 system_v
|
||||
sig2 = (i64 vmctx, i32, i32, i32) -> i32 system_v
|
||||
fn0 = sig0 u0:2
|
||||
fn1 = sig1 u0:0
|
||||
fn2 = sig2 u0:1
|
||||
fn0 = u0:2 sig0
|
||||
fn1 = u0:0 sig1
|
||||
fn2 = u0:1 sig2
|
||||
|
||||
ebb0(v0: i64, v1: i32, v2: i32):
|
||||
v3 = iconst.i32 0
|
||||
@@ -1038,7 +1038,7 @@ function %musl(f64 [%xmm0], i64 vmctx [%rdi]) -> f64 [%xmm0] system_v {
|
||||
gv0 = vmctx
|
||||
heap0 = static gv0, min 0, bound 0x0001_0000_0000, guard 0x8000_0000
|
||||
sig0 = (f64 [%xmm0], i32 [%rdi], i64 vmctx [%rsi]) -> f64 [%xmm0] system_v
|
||||
fn0 = sig0 u0:517
|
||||
fn0 = u0:517 sig0
|
||||
|
||||
ebb0(v0: f64, v1: i64):
|
||||
v3 = iconst.i64 0
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
test regalloc
|
||||
set is_64bit
|
||||
isa intel haswell
|
||||
isa x86 haswell
|
||||
|
||||
; Reported as https://github.com/Cretonne/cretonne/issues/216 from the Binaryen fuzzer.
|
||||
; Reported as https://github.com/cretonne/cretonne/issues/216 from the Binaryen fuzzer.
|
||||
;
|
||||
; The (old) coalescer creates a virtual register with two identical values.
|
||||
function %pr216(i32 [%rdi], i64 vmctx [%rsi]) -> i64 [%rax] system_v {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
test regalloc
|
||||
set is_64bit
|
||||
isa intel haswell
|
||||
isa x86 haswell
|
||||
|
||||
function %pr227(i32 [%rdi], i32 [%rsi], i32 [%rdx], i32 [%rcx], i64 vmctx [%r8]) system_v {
|
||||
gv0 = vmctx
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
test regalloc
|
||||
isa intel
|
||||
isa x86
|
||||
|
||||
; regex: V=v\d+
|
||||
; regex: REG=%r([abcd]x|[sd]i)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
test regalloc
|
||||
set is_64bit
|
||||
isa intel haswell
|
||||
isa x86 haswell
|
||||
|
||||
; This test case would create an EBB parameter that was a ghost value.
|
||||
; The coalescer would insert a copy of the ghost value, leading to verifier errors.
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
test regalloc
|
||||
isa intel
|
||||
isa x86
|
||||
|
||||
; This test covers the troubles when values with global live ranges are defined
|
||||
; by instructions with constrained register classes.
|
||||
;
|
||||
; The icmp_imm instrutions write their b1 result to the ABCD register class on
|
||||
; 32-bit Intel. So if we define 5 live values, they can't all fit.
|
||||
; 32-bit x86. So if we define 5 live values, they can't all fit.
|
||||
function %global_constraints(i32) {
|
||||
ebb0(v0: i32):
|
||||
v1 = icmp_imm eq v0, 1
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
test regalloc
|
||||
set is_64bit=1
|
||||
isa intel haswell
|
||||
isa x86 haswell
|
||||
|
||||
function %foo() system_v {
|
||||
ebb4:
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
test regalloc
|
||||
set is_64bit
|
||||
isa intel haswell
|
||||
isa x86 haswell
|
||||
|
||||
function u0:9(i64 [%rdi], f32 [%xmm0], f64 [%xmm1], i32 [%rsi], i32 [%rdx], i64 vmctx [%r14]) -> i64 [%rax] spiderwasm {
|
||||
ebb0(v0: i64, v1: f32, v2: f64, v3: i32, v4: i32, v5: i64):
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
test regalloc
|
||||
set is_64bit
|
||||
isa intel haswell
|
||||
isa x86 haswell
|
||||
|
||||
; Test combinations of constraints.
|
||||
;
|
||||
; The Intel ushr instruction requires its second operand to be passed in %rcx and its output is
|
||||
; The x86 ushr instruction requires its second operand to be passed in %rcx and its output is
|
||||
; tied to the first input operand.
|
||||
;
|
||||
; If we pass the same value to both operands, both constraints must be satisfied.
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
test regalloc
|
||||
set is_64bit=1
|
||||
isa intel haswell
|
||||
isa x86 haswell
|
||||
|
||||
function %test(i64) -> i64 system_v {
|
||||
ebb0(v0: i64):
|
||||
v2 = iconst.i64 12
|
||||
; This division clobbers two of its fixed input registers on Intel.
|
||||
; This division clobbers two of its fixed input registers on x86.
|
||||
; These are FixedTied constraints that the spiller needs to resolve.
|
||||
v5 = udiv v0, v2
|
||||
v6 = iconst.i64 13
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
test regalloc
|
||||
set is_64bit
|
||||
isa intel haswell
|
||||
isa x86 haswell
|
||||
|
||||
; regex: V=v\d+
|
||||
|
||||
; Filed as https://github.com/Cretonne/cretonne/issues/208
|
||||
; Filed as https://github.com/cretonne/cretonne/issues/208
|
||||
;
|
||||
; The verifier complains about a branch argument that is not in the same virtual register as the
|
||||
; corresponding EBB argument.
|
||||
@@ -16,8 +16,8 @@ function %pr208(i64 vmctx [%rdi]) system_v {
|
||||
heap0 = static gv0, min 0, bound 0x5000, guard 0x0040_0000
|
||||
sig0 = (i64 vmctx [%rdi]) -> i32 [%rax] system_v
|
||||
sig1 = (i64 vmctx [%rdi], i32 [%rsi]) system_v
|
||||
fn0 = sig0 u0:1
|
||||
fn1 = sig1 u0:3
|
||||
fn0 = u0:1 sig0
|
||||
fn1 = u0:3 sig1
|
||||
|
||||
ebb0(v0: i64):
|
||||
v1 = iconst.i32 0
|
||||
|
||||
@@ -5,7 +5,7 @@ isa riscv enable_e
|
||||
|
||||
; Check that we can handle a function return value that got spilled.
|
||||
function %spill_return() -> i32 {
|
||||
fn0 = function %foo() -> i32 system_v
|
||||
fn0 = %foo() -> i32 system_v
|
||||
|
||||
ebb0:
|
||||
v0 = call fn0()
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
test regalloc
|
||||
isa intel haswell
|
||||
isa x86 haswell
|
||||
|
||||
function %pr165() system_v {
|
||||
ebb0:
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
test regalloc
|
||||
set is_64bit
|
||||
isa intel
|
||||
isa x86
|
||||
|
||||
; Test case found by the Binaryen fuzzer.
|
||||
;
|
||||
; The spiller panics with a
|
||||
; 'Ran out of GPR registers when inserting copy before v68 = icmp.i32 eq v66, v67',
|
||||
; lib/cretonne/src/regalloc/spilling.rs:425:28 message.
|
||||
; lib/codegen/src/regalloc/spilling.rs:425:28 message.
|
||||
;
|
||||
; The process_reg_uses() function is trying to insert a copy before the icmp instruction in ebb4
|
||||
; and runs out of registers to spill. Note that ebb7 has a lot of dead parameter values.
|
||||
|
||||
@@ -70,7 +70,7 @@ ebb0(v1: i32):
|
||||
|
||||
; All values live across a call must be spilled
|
||||
function %across_call(i32) {
|
||||
fn0 = function %foo(i32)
|
||||
fn0 = %foo(i32)
|
||||
ebb0(v1: i32):
|
||||
; check: v1 = spill
|
||||
call fn0(v1)
|
||||
@@ -83,7 +83,7 @@ ebb0(v1: i32):
|
||||
|
||||
; The same value used for two function arguments.
|
||||
function %doubleuse(i32) {
|
||||
fn0 = function %xx(i32, i32)
|
||||
fn0 = %xx(i32, i32)
|
||||
ebb0(v0: i32):
|
||||
; check: $(c=$V) = copy v0
|
||||
call fn0(v0, v0)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
test compile
|
||||
|
||||
set is_64bit
|
||||
isa intel haswell
|
||||
isa x86 haswell
|
||||
|
||||
; This function contains unreachable blocks which trip up the register
|
||||
; allocator if they don't get cleared out.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
test regalloc
|
||||
|
||||
isa intel
|
||||
isa x86
|
||||
|
||||
; regex: V=v\d+
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
test verifier
|
||||
isa intel
|
||||
isa x86
|
||||
|
||||
; Simple, correct use of CPU flags.
|
||||
function %simple(i32) -> i32 {
|
||||
|
||||
@@ -42,14 +42,14 @@ function %type_mismatch_controlling_variable() {
|
||||
}
|
||||
|
||||
function %fn_call_too_few_args() {
|
||||
fn2 = function %great_fn(i32, f32)
|
||||
fn2 = %great_fn(i32, f32)
|
||||
ebb0:
|
||||
call fn2() ; error: mismatched argument count, got 0, expected 2
|
||||
return
|
||||
}
|
||||
|
||||
function %fn_call_too_many_args() {
|
||||
fn5 = function %best_fn()
|
||||
fn5 = %best_fn()
|
||||
ebb0:
|
||||
v0 = iconst.i64 56
|
||||
v1 = f32const 0.0
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
test compile
|
||||
|
||||
set is_64bit=0
|
||||
isa intel haswell
|
||||
isa x86 haswell
|
||||
|
||||
set is_64bit=1
|
||||
isa intel haswell
|
||||
isa x86 haswell
|
||||
|
||||
function %br_if(i32) -> i32 {
|
||||
ebb0(v0: i32):
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
test compile
|
||||
|
||||
set is_64bit=1
|
||||
isa intel haswell
|
||||
isa x86 haswell
|
||||
|
||||
function %i32_wrap_i64(i64) -> i32 {
|
||||
ebb0(v0: i64):
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
test compile
|
||||
|
||||
set is_64bit=0
|
||||
isa intel haswell
|
||||
isa x86 haswell
|
||||
|
||||
set is_64bit=1
|
||||
isa intel haswell
|
||||
isa x86 haswell
|
||||
|
||||
; Constants.
|
||||
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
test compile
|
||||
|
||||
set is_64bit=0
|
||||
isa intel haswell
|
||||
isa x86 haswell
|
||||
|
||||
set is_64bit=1
|
||||
isa intel haswell
|
||||
isa x86 haswell
|
||||
|
||||
function %f32_eq(f32, f32) -> i32 {
|
||||
ebb0(v0: f32, v1: f32):
|
||||
|
||||
@@ -4,7 +4,7 @@ test compile
|
||||
; We only test on 64-bit since the heap_addr instructions and vmctx parameters
|
||||
; explicitly mention the pointer width.
|
||||
set is_64bit=1
|
||||
isa intel haswell
|
||||
isa x86 haswell
|
||||
|
||||
function %f32_load(i32, i64 vmctx) -> f32 {
|
||||
gv0 = vmctx
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
test compile
|
||||
|
||||
set is_64bit=1
|
||||
isa intel haswell
|
||||
isa x86 haswell
|
||||
|
||||
; Constants.
|
||||
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
test compile
|
||||
|
||||
set is_64bit=0
|
||||
isa intel haswell
|
||||
isa x86 haswell
|
||||
|
||||
set is_64bit=1
|
||||
isa intel haswell
|
||||
isa x86 haswell
|
||||
|
||||
function %f64_eq(f64, f64) -> i32 {
|
||||
ebb0(v0: f64, v1: f64):
|
||||
|
||||
@@ -4,7 +4,7 @@ test compile
|
||||
; We only test on 64-bit since the heap_addr instructions and vmctx parameters
|
||||
; explicitly mention the pointer width.
|
||||
set is_64bit=1
|
||||
isa intel haswell
|
||||
isa x86 haswell
|
||||
|
||||
function %f64_load(i32, i64 vmctx) -> f64 {
|
||||
gv0 = vmctx
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
test compile
|
||||
|
||||
set is_64bit=0
|
||||
isa intel haswell
|
||||
isa x86 haswell
|
||||
|
||||
set is_64bit=1
|
||||
isa intel haswell
|
||||
isa x86 haswell
|
||||
|
||||
; Constants.
|
||||
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
test compile
|
||||
|
||||
set is_64bit=0
|
||||
isa intel haswell
|
||||
isa x86 haswell
|
||||
|
||||
set is_64bit=1
|
||||
isa intel haswell
|
||||
isa x86 haswell
|
||||
|
||||
function %i32_eqz(i32) -> i32 {
|
||||
ebb0(v0: i32):
|
||||
|
||||
@@ -4,7 +4,7 @@ test compile
|
||||
; We only test on 64-bit since the heap_addr instructions and vmctx parameters
|
||||
; explicitly mention the pointer width.
|
||||
set is_64bit=1
|
||||
isa intel haswell
|
||||
isa x86 haswell
|
||||
|
||||
function %i32_load(i32, i64 vmctx) -> i32 {
|
||||
gv0 = vmctx
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
test compile
|
||||
|
||||
set is_64bit=1
|
||||
isa intel haswell
|
||||
isa x86 haswell
|
||||
|
||||
; Constants.
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
test compile
|
||||
|
||||
set is_64bit=1
|
||||
isa intel haswell
|
||||
isa x86 haswell
|
||||
|
||||
function %i64_eqz(i64) -> i32 {
|
||||
ebb0(v0: i64):
|
||||
|
||||
@@ -4,7 +4,7 @@ test compile
|
||||
; We only test on 64-bit since the heap_addr instructions and vmctx parameters
|
||||
; explicitly mention the pointer width.
|
||||
set is_64bit=1
|
||||
isa intel haswell
|
||||
isa x86 haswell
|
||||
|
||||
function %i64_load(i32, i64 vmctx) -> i64 {
|
||||
gv0 = vmctx
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
test compile
|
||||
|
||||
set is_64bit=0
|
||||
isa intel haswell
|
||||
isa x86 haswell
|
||||
|
||||
set is_64bit=1
|
||||
isa intel haswell
|
||||
isa x86 haswell
|
||||
|
||||
function %select_i32(i32, i32, i32) -> i32 {
|
||||
ebb0(v0: i32, v1: i32, v2: i32):
|
||||
|
||||
@@ -4,7 +4,7 @@ cd $(dirname "$0")
|
||||
topdir="$(pwd)"
|
||||
|
||||
# All the cretonne-* crates have the same version number
|
||||
version="0.4.1"
|
||||
version="0.5.0"
|
||||
|
||||
# Update all of the Cargo.toml files.
|
||||
#
|
||||
@@ -27,8 +27,14 @@ cargo update
|
||||
|
||||
echo git commit -a -m "\"Bump version to $version"\"
|
||||
echo git push
|
||||
for crate in cretonne frontend native reader wasm; do
|
||||
for crate in entity codegen frontend native reader wasm module simplejit faerie umbrella ; do
|
||||
if [ "$crate" == "umbrella" ]; then
|
||||
dir="cretonne"
|
||||
else
|
||||
dir="$crate"
|
||||
fi
|
||||
|
||||
echo cargo publish --manifest-path "lib/$crate/Cargo.toml"
|
||||
done
|
||||
echo
|
||||
echo Then, go to https://github.com/Cretonne/cretonne/releases/ and define a new release.
|
||||
echo Then, go to https://github.com/cretonne/cretonne/releases/ and define a new release.
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
//! normalizing formatting and removing comments.
|
||||
|
||||
use CommandResult;
|
||||
use cton_reader::parse_functions;
|
||||
use cretonne_reader::parse_functions;
|
||||
use utils::read_to_string;
|
||||
|
||||
pub fn run(files: &[String]) -> CommandResult {
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
//! CLI tool to read Cretonne IR files and compile them into native code.
|
||||
|
||||
use cretonne::Context;
|
||||
use cretonne::print_errors::pretty_error;
|
||||
use cretonne::settings::FlagsOrIsa;
|
||||
use cretonne::{binemit, ir};
|
||||
use cton_reader::parse_test;
|
||||
use cretonne_codegen::Context;
|
||||
use cretonne_codegen::print_errors::pretty_error;
|
||||
use cretonne_codegen::settings::FlagsOrIsa;
|
||||
use cretonne_codegen::{binemit, ir};
|
||||
use cretonne_reader::parse_test;
|
||||
use std::path::Path;
|
||||
use std::path::PathBuf;
|
||||
use utils::{parse_sets_and_isa, read_to_string};
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
extern crate cretonne;
|
||||
extern crate cton_filetests;
|
||||
extern crate cton_reader;
|
||||
extern crate cton_wasm;
|
||||
extern crate cretonne_codegen;
|
||||
extern crate cretonne_filetests;
|
||||
extern crate cretonne_reader;
|
||||
extern crate cretonne_wasm;
|
||||
extern crate docopt;
|
||||
extern crate filecheck;
|
||||
#[macro_use]
|
||||
@@ -9,7 +9,7 @@ extern crate serde_derive;
|
||||
extern crate tempdir;
|
||||
extern crate term;
|
||||
|
||||
use cretonne::{timing, VERSION};
|
||||
use cretonne_codegen::{timing, VERSION};
|
||||
use docopt::Docopt;
|
||||
use std::io::{self, Write};
|
||||
use std::process;
|
||||
@@ -86,7 +86,7 @@ fn cton_util() -> CommandResult {
|
||||
|
||||
// Find the sub-command to execute.
|
||||
let result = if args.cmd_test {
|
||||
cton_filetests::run(args.flag_verbose, &args.arg_file).map(|_time| ())
|
||||
cretonne_filetests::run(args.flag_verbose, &args.arg_file).map(|_time| ())
|
||||
} else if args.cmd_cat {
|
||||
cat::run(&args.arg_file)
|
||||
} else if args.cmd_filecheck {
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
//! in graphviz format.
|
||||
|
||||
use CommandResult;
|
||||
use cretonne::cfg_printer::CFGPrinter;
|
||||
use cton_reader::parse_functions;
|
||||
use cretonne_codegen::cfg_printer::CFGPrinter;
|
||||
use cretonne_reader::parse_functions;
|
||||
use utils::read_to_string;
|
||||
|
||||
pub fn run(files: &[String]) -> CommandResult {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
//! Utility functions.
|
||||
|
||||
use cretonne::isa;
|
||||
use cretonne::isa::TargetIsa;
|
||||
use cretonne::settings::{self, FlagsOrIsa};
|
||||
use cton_reader::{parse_options, Location};
|
||||
use cretonne_codegen::isa;
|
||||
use cretonne_codegen::isa::TargetIsa;
|
||||
use cretonne_codegen::settings::{self, FlagsOrIsa};
|
||||
use cretonne_reader::{parse_options, Location};
|
||||
use std::fs::File;
|
||||
use std::io::{self, Read};
|
||||
use std::path::Path;
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
//! CLI tool to use the functions provided by the [cretonne-wasm](../cton_wasm/index.html) crate.
|
||||
//! CLI tool to use the functions provided by the [cretonne-wasm](../cretonne_wasm/index.html)
|
||||
//! crate.
|
||||
//!
|
||||
//! Reads Wasm binary files, translates the functions' code to Cretonne IR.
|
||||
#![cfg_attr(feature = "cargo-clippy", allow(too_many_arguments, cyclomatic_complexity))]
|
||||
|
||||
use cretonne::Context;
|
||||
use cretonne::print_errors::{pretty_error, pretty_verifier_error};
|
||||
use cretonne::settings::FlagsOrIsa;
|
||||
use cton_wasm::{translate_module, DummyEnvironment, ModuleEnvironment};
|
||||
use cretonne_codegen::Context;
|
||||
use cretonne_codegen::print_errors::{pretty_error, pretty_verifier_error};
|
||||
use cretonne_codegen::settings::FlagsOrIsa;
|
||||
use cretonne_wasm::{translate_module, DummyEnvironment, ModuleEnvironment};
|
||||
use std::error::Error;
|
||||
use std::fs::File;
|
||||
use std::io;
|
||||
|
||||
@@ -31,13 +31,13 @@ fi
|
||||
# Check if any Python files have changed since we last checked them.
|
||||
tsfile=$topdir/target/meta-checked
|
||||
if [ -f $tsfile ]; then
|
||||
needcheck=$(find $topdir/lib/cretonne/meta -name '*.py' -newer $tsfile)
|
||||
needcheck=$(find $topdir/lib/codegen/meta -name '*.py' -newer $tsfile)
|
||||
else
|
||||
needcheck=yes
|
||||
fi
|
||||
if [ -n "$needcheck" ]; then
|
||||
banner "$(python --version 2>&1), $(python3 --version 2>&1)"
|
||||
$topdir/lib/cretonne/meta/check.sh
|
||||
$topdir/lib/codegen/meta/check.sh
|
||||
touch $tsfile || echo no target directory
|
||||
fi
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ function banner() {
|
||||
}
|
||||
|
||||
# Test those packages which have no_std support.
|
||||
LIBS="cretonne frontend wasm native"
|
||||
LIBS="codegen frontend wasm native"
|
||||
cd "$topdir"
|
||||
for LIB in $LIBS
|
||||
do
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
extern crate cton_filetests;
|
||||
extern crate cretonne_filetests;
|
||||
|
||||
#[test]
|
||||
fn filetests() {
|
||||
// Run all the filetests in the following directories.
|
||||
cton_filetests::run(false, &["filetests".into(), "docs".into()]).expect("test harness");
|
||||
cretonne_filetests::run(false, &["filetests".into(), "docs".into()]).expect("test harness");
|
||||
}
|
||||
|
||||
@@ -1,20 +1,18 @@
|
||||
[package]
|
||||
authors = ["The Cretonne Project Developers"]
|
||||
name = "cretonne"
|
||||
version = "0.4.1"
|
||||
name = "cretonne-codegen"
|
||||
version = "0.5.0"
|
||||
description = "Low-level code generator library"
|
||||
license = "Apache-2.0"
|
||||
documentation = "https://cretonne.readthedocs.io/"
|
||||
repository = "https://github.com/Cretonne/cretonne"
|
||||
repository = "https://github.com/cretonne/cretonne"
|
||||
readme = "README.md"
|
||||
keywords = ["compile", "compiler", "jit"]
|
||||
build = "build.rs"
|
||||
|
||||
[lib]
|
||||
name = "cretonne"
|
||||
|
||||
[dependencies]
|
||||
# It is a goal of the cretonne crate to have minimal external dependencies.
|
||||
cretonne-entity = { path = "../entity", version = "0.5.0" }
|
||||
# It is a goal of the cretonne-codegen crate to have minimal external dependencies.
|
||||
# Please don't add any unless they are essential to the task of creating binary
|
||||
# machine code. Integration tests that need external dependencies can be
|
||||
# accomodated in `tests`.
|
||||
@@ -35,4 +33,4 @@ core = ["hashmap_core"]
|
||||
|
||||
[badges]
|
||||
maintenance = { status = "experimental" }
|
||||
travis-ci = { repository = "Cretonne/cretonne" }
|
||||
travis-ci = { repository = "cretonne/cretonne" }
|
||||
@@ -1,7 +1,7 @@
|
||||
// Build script.
|
||||
//
|
||||
// This program is run by Cargo when building lib/cretonne. It is used to generate Rust code from
|
||||
// the language definitions in the lib/cretonne/meta directory.
|
||||
// This program is run by Cargo when building lib/codegen. It is used to generate Rust code from
|
||||
// the language definitions in the lib/codegen/meta directory.
|
||||
//
|
||||
// Environment:
|
||||
//
|
||||
@@ -77,7 +77,7 @@ fn main() {
|
||||
#[derive(Copy, Clone)]
|
||||
enum Isa {
|
||||
Riscv,
|
||||
Intel,
|
||||
X86,
|
||||
Arm32,
|
||||
Arm64,
|
||||
}
|
||||
@@ -103,14 +103,14 @@ impl Isa {
|
||||
|
||||
/// Returns all supported isa targets.
|
||||
fn all() -> [Isa; 4] {
|
||||
[Isa::Riscv, Isa::Intel, Isa::Arm32, Isa::Arm64]
|
||||
[Isa::Riscv, Isa::X86, Isa::Arm32, Isa::Arm64]
|
||||
}
|
||||
|
||||
/// Returns name of the isa target.
|
||||
fn name(&self) -> &'static str {
|
||||
match *self {
|
||||
Isa::Riscv => "riscv",
|
||||
Isa::Intel => "intel",
|
||||
Isa::X86 => "x86",
|
||||
Isa::Arm32 => "arm32",
|
||||
Isa::Arm64 => "arm64",
|
||||
}
|
||||
@@ -120,7 +120,7 @@ impl Isa {
|
||||
fn is_arch_applicable(&self, arch: &str) -> bool {
|
||||
match *self {
|
||||
Isa::Riscv => arch == "riscv",
|
||||
Isa::Intel => ["x86_64", "i386", "i586", "i686"].contains(&arch),
|
||||
Isa::X86 => ["x86_64", "i386", "i586", "i686"].contains(&arch),
|
||||
Isa::Arm32 => arch.starts_with("arm") || arch.starts_with("thumb"),
|
||||
Isa::Arm64 => arch == "aarch64",
|
||||
}
|
||||
@@ -20,7 +20,7 @@ stack_slot = EntityRefKind('stack_slot', 'A stack slot.')
|
||||
global_var = EntityRefKind('global_var', 'A global variable.')
|
||||
|
||||
#: A reference to a function sugnature declared in the function preamble.
|
||||
#: Tbis is used to provide the call signature in an indirect call instruction.
|
||||
#: This is used to provide the call signature in a call_indirect instruction.
|
||||
sig_ref = EntityRefKind('sig_ref', 'A function signature.')
|
||||
|
||||
#: A reference to an external function declared in the function preamble.
|
||||
@@ -53,7 +53,7 @@ BranchIcmp = InstructionFormat(intcc, VALUE, VALUE, ebb, VARIABLE_ARGS)
|
||||
BranchTable = InstructionFormat(VALUE, entities.jump_table)
|
||||
|
||||
Call = InstructionFormat(func_ref, VARIABLE_ARGS)
|
||||
IndirectCall = InstructionFormat(sig_ref, VALUE, VARIABLE_ARGS)
|
||||
CallIndirect = InstructionFormat(sig_ref, VALUE, VARIABLE_ARGS)
|
||||
FuncAddr = InstructionFormat(func_ref)
|
||||
|
||||
Load = InstructionFormat(memflags, VALUE, offset32)
|
||||
@@ -65,6 +65,9 @@ expand_flags = XFormGroup('expand_flags', """
|
||||
expand.custom_legalize(insts.global_addr, 'expand_global_addr')
|
||||
expand.custom_legalize(insts.heap_addr, 'expand_heap_addr')
|
||||
|
||||
# Custom expansions for calls.
|
||||
expand.custom_legalize(insts.call, 'expand_call')
|
||||
|
||||
# Custom expansions that need to change the CFG.
|
||||
# TODO: Add sufficient XForm syntax that we don't need to hand-code these.
|
||||
expand.custom_legalize(insts.trapz, 'expand_cond_trap')
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user