Commit 917adf40 authored by Isaac Oscar Gariano's avatar Isaac Oscar Gariano

Merge branch 'develop' into aarch64

parents 95e36fa2 1d4c17be
......@@ -3,21 +3,10 @@
**/__pycache__/*
**/.cache/*
**/emit/*
**/temp/*
Cargo.lock
*.log
*.DS_Store
*.swp
.idea
*.pyc
*.o
*.dylib
**mu-client-pypy**
**RPySOM**
.gitignore
cmake-build-debug/*
Notes/*
CMakeLists.txt
*.iml
.rsync-filter
*.so
# This file is a template, and might need editing before it works on your project.
# Unofficial language image. Look for the different tagged releases at:
# https://hub.docker.com/r/scorpil/rust/tags/
image: "qinsoon/ubuntu-zebu-test:latest"
# Optional: Pick zero or more services to be used on all builds.
# Only needed when using a docker container to run your tests in.
# Check out: http://docs.gitlab.com/ce/ci/docker/using_docker_images.html#what-is-service
#services:
# - mysql:latest
# - redis:latest
# - postgres:latest
# Optional: Install a C compiler, cmake and git into the container.
# You will often need this when you (or any of your dependencies) depends on C code.
#before_script:
#- apt-get update -yqq
#- apt-get install -yqq --no-install-recommends build-essential
# Use cargo to test the project
# cache:
# key: "$CI_BUILD_STAGE/$CI_BUILD_REF_NAME"
# paths:
# - .cargo/registry/cache
# - .cargo/registry/index
# - target
# - Cargo.lock
stages:
- build
- test
- rustfmt
before_script:
- export PATH=$PATH:/root/.cargo/bin
- export MU_ZEBU=$CI_PROJECT_DIR
- export ZEBU_BUILD=release
- export CARGO_HOME=.cargo
- export CC=clang
build:
stage: build
......@@ -41,13 +23,6 @@ build:
- target/release/libmu.a
- target/release/lib-*
before_script:
- export PATH=$PATH:/root/.cargo/bin
- export MU_ZEBU=$CI_PROJECT_DIR
- export ZEBU_BUILD=release
- export CARGO_HOME=.cargo
- export CC=clang
test:cargo:api:
stage: test
script:
......@@ -137,4 +112,9 @@ testjit:som:
- git checkout mu-rewrite
- git apply pypy.patch
- cd $CI_PROJECT_DIR/tests/test_jit
- MU_LOG_LEVEL=info LD_LIBRARY_PATH=. RUST_BACKTRACE=1 PYTHONPATH=mu-client-pypy:RPySOM/src RPYSOM=RPySOM pytest test_som.py -v --color=yes
\ No newline at end of file
- MU_LOG_LEVEL=info LD_LIBRARY_PATH=. RUST_BACKTRACE=1 PYTHONPATH=mu-client-pypy:RPySOM/src RPYSOM=RPySOM pytest test_som.py -v --color=yes
rustfmt:
stage: rustfmt
script:
- rustup run nightly cargo fmt -- --write-mode=diff src/ast/src/lib.rs src/gc/src/lib.rs src/utils/src/lib.rs --verbose
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>mu</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>com.github.rustdt.ide.core.Builder</name>
<triggers>clean,full,incremental,</triggers>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>com.github.rustdt.ide.core.nature</nature>
</natures>
</projectDescription>
build_targets=<?xml version\="1.0" encoding\="UTF-8" standalone\="no"?>\n<build_targets xmlns\="com.github.rustdt.ide.core">\n<target auto_enabled\="false" config\="build" n_enabled\="true" version2\="true"/>\n<target auto_enabled\="false" config\="check" n_enabled\="false" version2\="true">\n<command_invocation append_env\="true" command_arguments\="${CARGO_TOOL_PATH} build">\n<env_vars/>\n</command_invocation>\n</target>\n</build_targets>\n
eclipse.preferences.version=1
......@@ -31,10 +31,11 @@ jit = []
gcc = "*"
[dependencies]
ast = {path = "src/ast"}
utils = {path = "src/utils"}
gc = {path = "src/gc"}
mu_ast = {path = "src/ast"}
mu_utils = {path = "src/utils"}
mu_gc = {path = "src/gc"}
rodal = { git = "https://gitlab.anu.edu.au/mu/rodal", version = ">= 0.0.5" }
libc="*"
field-offset = "*"
libloading = "*"
......
This diff is collapsed.
# Zebu VM (a fast implementation of Mu Micro VM)
[![build status](https://gitlab.anu.edu.au/mu/mu-impl-fast/badges/master/build.svg)](https://gitlab.anu.edu.au/mu/mu-impl-fast/commits/master)
Mu Micro VM is a substrate language virtual machine. Mu executes its
language-/platform-neutural immediate representation to provide common
low-level abstractions for programming language implementation, such as
machine code generation and execution, garbage collection and concurrency.
With Mu, language developers only need to care about language-specific
optimisation and execution while leaving the low-level part to Mu Micro VM.
Zebu VM is a fast implementation of Mu, developed in Australia National
University.
## Platform support
Zebu supports the follow platforms:
* x86_64/linux (CI)
* aarch64/linux
* x86_64/macos (macOS 10.12+)
## Mu specification coverage
Zebu does not implement full Mu specification yet.
[This label](https://gitlab.anu.edu.au/mu/mu-impl-fast/issues?label_name%5B%5D=spec+coverage)
in the issue tracker keeps track of unimplemented features, or features that
are not compliant to Mu spec.
## Building
You will need:
* rust version 1.18 (03fc9d622 2017-06-06)
* clang 4.0+
* internet connection (as Rust will download dependencies)
To build Zebu with release build,
```
cd path/to/zebu
MU_ZEBU=. CC=clang cargo build --release
```
you will get shared and static libraries for Zebu under `target/release/`
that you can link against in your language implementation.
You can also build Zebu in debug.
```
cd path/to/zebu
MU_ZEBU=. CC=clang cargo build
```
## Testing
Zebu repository includes two test suites:
* cargo test
* pytest
#### Running tests with cargo test
```
cd path/to/zebu
MU_ZEBU=. CC=clang RUST_TEST_THREADS=1 cargo test --release 2>/dev/null
```
#### Running tests with pytest
To facilitate tests, Zebu uses RPython (which targets Mu as backend) for some
of tests in this suite.
Download [PyPyMu](https://gitlab.anu.edu.au/mu/mu-client-pypy)
```
cd path/to/zebu
git clone https://gitlab.anu.edu.au/mu/mu-client-pypy.git tests/test_jit/mu-client-pypy
cd tests/test_jit/mu-client-pypy
git checkout mu-rewrite
git apply pypy.patch
```
Download [RPySOM](https://github.com/microvm/RPySOM)
```
cd path/to/zebu
git clone https://gitlab.anu.edu.au/mu/x-RPySOM.git tests/test_jit/RPySOM
cd tests/test_jit/RPySOM
git submodule init
git submodule update
```
Running pytest (you will need Python 2.7 with pytest module)
```
cd path/to/zebu/tests/test_jit
export DYLD_LIBRARY_PATH=.
export MU_ZEBU=path/to/zebu
export MU_LOG_LEVEL=none
export PYTHONPATH=mu-client-pypy:RPySOM/src
export RPYSOM=RPySOM
export ZEBU_BUILD=release
export CC=clang
export SPAWN_PROC=1
python2 -m pytest test*.py -v
```
## Using Zebu for your language implementation
Zebu provides the C binding for its API declared in
[mu-fastimpl.h](src/vm/api/mu-fastimpl.h). The APIs are defined
in [Mu specification](https://gitlab.anu.edu.au/mu/mu-spec).
The header also includes Zebu-specific APIs, such as `mu_fastimpl_new()`.
Zebu allows the user to set options when creating a new instance.
The options can be found in [vm_options.rs](src/vm/vm_options.rs).
## Bug reports
As Zebu is still in its early development, we expect bugs and
missing features. We appreciate if you can report to
[Issues](https://gitlab.anu.edu.au/mu/mu-impl-fast/issues).
Our priority for Zebu development is driven by the issue tracker along with
two client implementations that are being actively developed in ANU,
[PyPy-Mu](https://gitlab.anu.edu.au/mu/mu-client-pypy)
and [GHC-Mu](https://gitlab.anu.edu.au/mu/mu-client-ghc).
## License
Zebu uses Apache 2.0. See the [license](LICENSE).
# Copyright 2017 The Australian National University
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
set -e
if [ -z "$MU_ZEBU" ]
then
export MU_ZEBU=$PWD
fi
export MU_LOG_LEVEL=none
export RUST_TEST_THREADS=1
export RUST_BACKTRACE=0
export PYTHONPATH="$MU_ZEBU/tests/test_jit/mu-client-pypy/:$MU_ZEBU/tests/test_jit/RPySOM/src"
export LD_LIBRARY_PATH="$MU_ZEBU/tests/test_jit/:$MU_ZEBU/tests/test_jit"
export ZEBU_BUILD=release
rm -rf $MU_ZEBU/emit
rm -rf $MU_ZEBU/tests/test_jit/emit
#cargo clean
cargo test --release --no-run --color=always 2>&1 | tee build_out.txt
$(exit ${PIPESTATUS[0]}) # this command will exit the shell but only if the above cargo test failed
/usr/bin/time -f "finished in %e secs" -a -o cargo_test_out.txt ./test-release --color=always 2>/dev/null | tee cargo_test_out.txt
cd $MU_ZEBU/tests/test_jit/
if [ -d "./mu-client-pypy" ]
then
git -C ./mu-client-pypy pull
else
git clone https://gitlab.anu.edu.au/mu/mu-client-pypy.git
git -C ./mu-client-pypy checkout mu-rewrite
git -C ./mu-client-pypy apply pypy.patch
fi
if [ -d "./RPySOM" ]
then
git -C ./RPySOM pull
else
git clone https://github.com/microvm/RPySOM.git
git -C ./RPySOM submodule init
git -C ./RPySOM submodule update
fi
pytest test_*.py -v --color=yes 2>&1 | tee $MU_ZEBU/pytest_out.txt
trailing_comma = "Never"
......@@ -13,7 +13,7 @@
# limitations under the License.
[package]
name = "ast"
name = "mu_ast"
version = "0.0.1"
authors = ["qinsoon <qinsoon@gmail.com>"]
......@@ -21,7 +21,7 @@ authors = ["qinsoon <qinsoon@gmail.com>"]
crate-type = ["rlib"]
[dependencies]
utils = {path = "../utils"}
mu_utils = {path = "../utils"}
lazy_static = "*"
log = "*"
simple_logger = "*"
......
This diff is collapsed.
This diff is collapsed.
......@@ -15,6 +15,7 @@
//! # MuIR AST crate
//!
//! This crate provides data structures to allow construct MuIR in Rust code, including:
//!
//! * types
//! * ir
//! * MuFunction
......@@ -35,7 +36,7 @@ extern crate rodal;
extern crate simple_logger;
#[macro_use]
extern crate lazy_static;
extern crate utils;
extern crate mu_utils as utils;
/// all data structures for MuIR is an *MuEntity*
/// which has a unique MuID, and an optional MuName
......
......@@ -97,7 +97,7 @@ impl CmpOp {
FUGT => FULT,
FULT => FUGT,
_ => self, // all other comparisons are symmetric
_ => self // all other comparisons are symmetric
}
}
......@@ -142,7 +142,7 @@ impl CmpOp {
FONE => FUEQ,
FFALSE => FTRUE,
FTRUE => FFALSE,
FTRUE => FFALSE
}
}
......@@ -154,7 +154,7 @@ impl CmpOp {
SLT => ULT,
SGT => UGT,
SLE => ULE,
_ => self,
_ => self
}
}
......@@ -169,16 +169,7 @@ impl CmpOp {
pub fn is_int_cmp(self) -> bool {
use op::CmpOp::*;
match self {
EQ
| NE
| SGE
| SGT
| SLE
| SLT
| UGE
| UGT
| ULE
| ULT => true,
EQ | NE | SGE | SGT | SLE | SLT | UGE | UGT | ULE | ULT => true,
_ => false
}
}
......@@ -186,7 +177,7 @@ impl CmpOp {
pub fn is_symmetric(self) -> bool {
use op::CmpOp::*;
match self {
EQ | NE | FORD| FUNO| FUNE | FUEQ | FONE | FOEQ => true,
EQ | NE | FORD | FUNO | FUNE | FUEQ | FONE | FOEQ => true,
_ => false
}
}
......@@ -221,4 +212,4 @@ pub enum AtomicRMWOp {
MIN,
UMAX,
UMIN
}
\ No newline at end of file
}
......@@ -23,4 +23,4 @@ pub type P<T> = Arc<T>;
/// Construct a `P<T>` from a `T` value.
pub fn P<T>(value: T) -> P<T> {
Arc::new(value)
}
\ No newline at end of file
}
This diff is collapsed.
......@@ -44,7 +44,7 @@ pub trait CodeGenerator {
fn add_cfi_def_cfa_offset(&mut self, offset: i32);
fn add_cfi_offset(&mut self, reg: Reg, offset: i32);
//==================================================================================================
//===========================================================================================
// emit code to adjust frame
fn emit_frame_grow(&mut self); // Emits a SUB
......@@ -57,33 +57,37 @@ pub trait CodeGenerator {
fn emit_ldr_callee_saved(&mut self, dest: Reg, src: Mem);
fn emit_str_callee_saved(&mut self, dest: Mem, src: Reg);
//==================================================================================================
//===========================================================================================
/* Bellow ar all ARMv8-A Aarch64 instruction menmonics (with all operand modes) except:
PRFM, PRFUM, CRC32*
All advanced SIMD instructions (except MOVI)
NOTE:
with loads and stores the menmonic indicated may be given a suffix indicating the size and signenedness of the access
also b_cond's menmononic is 'B.cond' (where cond is the value of the 'cond' parameter)
all other instructions have the menmonic being the first word of the function name after emit_
with loads and stores the menmonic indicated may be given a suffix indicating the size
and signenedness of the access also b_cond's menmononic is 'B.cond' (where cond is the
value of the 'cond' parameter) all other instructions have the menmonic being the first
word of the function name after emit_
(subsequent words are used to disambiguate different overloads)
NOTE unless otherwise indicated:
An instruction that dosn't start with an F operates on GPRS, those that start with an F operate on FPRs.
All instructions operate on 32-bit and 64-bit registers (but all register arguments must be the same size)
Also all arguments that may take the SP can't take the ZR (and vice versa)
An instruction that dosn't start with an F operates on GPRS, those that start with
an F operate on FPRs. All instructions operate on 32-bit and 64-bit registers (but all
register arguments must be the same size) Also all arguments that may take the SP can't
take the ZR (and vice versa)
*/
// loads
fn emit_ldr(&mut self, dest: Reg /*GPR or FPR*/, src: Mem, signed: bool); // supports the full full range of addressing modes
// supports the full full range of addressing modes
fn emit_ldr(&mut self, dest: Reg /*GPR or FPR*/, src: Mem, signed: bool);
fn emit_ldtr(&mut self, dest: Reg, src: Mem, signed: bool); // [base, #simm9]
fn emit_ldur(&mut self, dest: Reg /*GPR or FPR*/, src: Mem, signed: bool); // [base, #simm9]
fn emit_ldxr(&mut self, dest: Reg, src: Mem); // [base]
fn emit_ldaxr(&mut self, dest: Reg, src: Mem); // [base]
fn emit_ldar(&mut self, dest: Reg, src: Mem); // [base]
fn emit_ldp(&mut self, dest1: Reg, dest2: Reg /*GPR or FPR*/, src: Mem); // [base, #simm7], [base], #simm7, [base, #simm7]!
// [base, #simm7], [base], #simm7, [base, #simm7]!
fn emit_ldp(&mut self, dest1: Reg, dest2: Reg /*GPR or FPR*/, src: Mem);
fn emit_ldxp(&mut self, dest1: Reg, dest2: Reg, src: Mem); // [base]
fn emit_ldaxp(&mut self, dest1: Reg, dest2: Reg, src: Mem); // [base]
fn emit_ldnp(
......@@ -94,14 +98,16 @@ pub trait CodeGenerator {
); // [base, #simm7]
// Stores
fn emit_str(&mut self, dest: Mem, src: Reg /*GPR or FPR*/); // supports the full full range of addressing modes
// supports the full full range of addressing modes
fn emit_str(&mut self, dest: Mem, src: Reg /*GPR or FPR*/);
fn emit_sttr(&mut self, dest: Mem, src: Reg); // [base, #simm9]
fn emit_stur(&mut self, dest: Mem, src: Reg /*GPR or FPR*/); // [base, #simm9]
fn emit_stlr(&mut self, dest: Mem, src: Reg); // [base]
fn emit_stxr(&mut self, dest: Mem, status: Reg, src: Reg); // [base]
fn emit_stlxr(&mut self, dest: Mem, status: Reg, src: Reg); // [base]
fn emit_stp(&mut self, dest: Mem, src1: Reg, src2: Reg); // [base, #simm7], [base], #simm7, [base, #simm7]!
// [base, #simm7], [base], #simm7, [base, #simm7]!
fn emit_stp(&mut self, dest: Mem, src1: Reg, src2: Reg);
fn emit_stxp(&mut self, dest: Mem, status: Reg, src1: Reg, src2: Reg); // [base]
fn emit_stlxp(&mut self, dest: Mem, status: Reg, src1: Reg, src2: Reg); // [base]
fn emit_stnp(
......@@ -150,7 +156,8 @@ pub trait CodeGenerator {
fn emit_adrp(&mut self, dest: Reg, src: Mem);
// Unary ops
fn emit_mov(&mut self, dest: Reg /*GPR or SP or ZR*/, src: Reg /*GPR or SP or ZR*/); // The SP and ZR cannot both be used
// The SP and ZR cannot both be used
fn emit_mov(&mut self, dest: Reg /*GPR or SP or ZR*/, src: Reg /*GPR or SP or ZR*/);
fn emit_mvn(&mut self, dest: Reg, src: Reg);
fn emit_neg(&mut self, dest: Reg, src: Reg);
fn emit_negs(&mut self, dest: Reg, src: Reg);
......@@ -180,7 +187,8 @@ pub trait CodeGenerator {
fn emit_fcvtpu(&mut self, dest: Reg /*GPR, may have different size*/, src: Reg);
fn emit_fcvtzs(&mut self, dest: Reg /*GPR, may have different size*/, src: Reg);
fn emit_fcvtzu(&mut self, dest: Reg /*GPR, may have different size*/, src: Reg);
fn emit_fmov(&mut self, dest: Reg, src: Reg); // One register must be an FPR, the other may be a GPR or an FPR
// One register must be an FPR, the other may be a GPR or an FPR
fn emit_fmov(&mut self, dest: Reg, src: Reg);
fn emit_fneg(&mut self, dest: Reg, src: Reg);
fn emit_frinta(&mut self, dest: Reg, src: Reg);
fn emit_frinti(&mut self, dest: Reg, src: Reg);
......
......@@ -12,11 +12,13 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#![allow(dead_code)]
// TODO: CHECK THAT THE TYPE OF EVERY MEMORY LOCATION HAS THE CORRECT SIZE
// (the size should be size of the area in memory that it is referring to, and will indicate
// how much data any load/store instructions that uses it will operate on
// (so it should be [1], 8, 16, 32, 64, or 128 bits in size (when using emit_mem, it can have other sizes before this))
// (so it should be [1], 8, 16, 32, 64, or 128 bits in size (when using emit_mem,
// it can have other sizes before this))
#![allow(non_upper_case_globals)]
// TODO: Move architecture independent codes in here, inst_sel and asm_backend to somewhere else...
......@@ -126,7 +128,7 @@ GPR_ALIAS!(X27_ALIAS: (54, X27) -> W27);
GPR_ALIAS!(X28_ALIAS: (56, X28) -> W28);
GPR_ALIAS!(X29_ALIAS: (58, X29) -> W29);
GPR_ALIAS!(X30_ALIAS: (60, X30) -> W30);
GPR_ALIAS!(SP_ALIAS: (62, SP) -> WSP); // Special register (only some instructions can reference it)
GPR_ALIAS!(SP_ALIAS: (62, SP) -> WSP); // Special register(only some instructions can reference it)
GPR_ALIAS!(XZR_ALIAS: (64, XZR) -> WZR); // Pseudo register, not to be used by register allocator
// Aliases
......@@ -137,7 +139,6 @@ ALIAS!(X18 -> PR); // Platform Register (NEVER TOUCH THIS REGISTER (Unless you c
ALIAS!(X29 -> FP); // Frame Pointer (can be used as a normal register when not calling or returning)
ALIAS!(X30 -> LR); // Link Register (not supposed to be used for any other purpose)
lazy_static! {
pub static ref GPR_ALIAS_TABLE : LinkedHashMap<MuID, Vec<P<Value>>> = {
let mut ret = LinkedHashMap::new();
......@@ -330,7 +331,6 @@ pub fn primitive_byte_size(ty: &P<MuType>) -> usize {
}
}
#[allow(dead_code)]
lazy_static! {
// Note: these are the same as the ARGUMENT_GPRS
pub static ref RETURN_GPRS : [P<Value>; 8] = [
......@@ -394,7 +394,6 @@ lazy_static! {
//X18.clone(), // Platform Register
];
/*#[allow(dead_code)]
static ref ALL_GPRS : [P<Value>; 30] = [
X0.clone(),
X1.clone(),
......@@ -427,7 +426,7 @@ lazy_static! {
X28.clone(),
X29.clone(), // Frame Pointer
X30.clone() // Link Register
];*/
];
}
pub const FPR_ID_START: usize = 100;
......@@ -584,7 +583,6 @@ lazy_static!{
D31.clone()
];
/*#[allow(dead_code)]
static ref ALL_FPRS : [P<Value>; 32] = [
D0.clone(),
D1.clone(),
......@@ -620,7 +618,7 @@ lazy_static!{
D29.clone(),
D30.clone(),
D31.clone()
];*/
];
}
lazy_static! {
......@@ -961,7 +959,8 @@ pub fn is_valid_f32_imm(val: f32) -> bool {
((uval & !(0b1111111111111 << 0x13)) == 0)
}
// Reduces the given floating point constant to 8-bits (if it won't loose precision, otherwise returns 0)
// Reduces the given floating point constant to 8-bits
// (if it won't loose precision, otherwise returns 0)
pub fn is_valid_f64_imm(val: f64) -> bool {
use std::mem;
......@@ -1005,7 +1004,8 @@ pub fn replicate_logical_imm(val: u64, n: usize) -> u64 {
}
// 'val' is a valid logical immediate if the binary value of ROR(val, r) matches the regular expresion
// 'val' is a valid logical immediate if the binary value of ROR(val, r)
// matches the regular expression
// (0{k-x}1{x}){m/k}
// for some r, k that divides N, 2 <= k <= n, and x with 0 < x < k
// (note: 0 =< r < k);
......@@ -1166,8 +1166,8 @@ fn get_condition_codes(op: op::CmpOp) -> Vec<&'static str> {
}
}
// if t is a homogenouse floating point aggregate
// (i.e. an array or struct where each element is the same floating-point type, and there are at most 4 elements)
// if t is a homogenouse floating point aggregate (i.e. an array or struct
// where each element is the same floating-point type, and there are at most 4 elements)
// returns the number of elements, otherwise returns 0
fn hfa_length(t: &P<MuType>) -> usize {
......@@ -1484,7 +1484,8 @@ pub fn make_value_int_const(val: u64, vm: &VM) -> P<Value> {
// Replaces the zero register with a temporary whose value is zero (or returns the orignal register)
/* TODO use this function for the following arguments:
We can probabbly allow the zero register to be the second argument to an _ext function (as the assembler will simply use the shifted-register encoding, which allows it)
We can probabbly allow the zero register to be the second argument to an _ext function
(as the assembler will simply use the shifted-register encoding, which allows it)
add[,s1] // tirival
add_ext[d, s1] // trivial
add_imm[d, s1] // trivial
......@@ -1509,7 +1510,8 @@ cmn_imm[s1] // not trivial (sets flags)
cmp_ext[s1] // not trivial (sets flags)
cmp_imm[s1] // not trivial (sets flags)
(they are all (or did I miss some??) places that the SP can be used, which takes up the encoding of the ZR
(they are all (or did I miss some??) places that the SP can be used,
which takes up the encoding of the ZR
I believe the Zero register can be used in all other places that an integer register is expected
(BUT AM NOT CERTAIN)
*/
......@@ -2002,7 +2004,7 @@ pub fn emit_ireg_value(
&Constant::Int(val) => {
// TODO Deal with zero case
/*if val == 0 {
// TODO: Are there any (integer) instructions that can't use the Zero register?
// TODO: Are there any (integer) instructions that can't use the Zero reg?
// Use the zero register (saves having to use a temporary)
get_alias_for_length(XZR.id(), get_bit_size(&pv.ty, vm))
} else {*/
......@@ -2150,13 +2152,15 @@ pub fn emit_mem(
emit_mov_u64(backend, &offset, offset_val as u64);
Some(offset)
} else {
// We will be using a store/load pair which dosn't support register offsets
// We will be using a store/load pair
// which dosn't support register offsets
return emit_mem_base(backend, &pv, f_context, vm);
}
} else {
let offset = emit_ireg_value(backend, offset, f_context, vm);
// TODO: If scale == (2^n)*m (for some m), set shift = n, and multiply index by m
// TODO: If scale == (2^n)*m (for some m), set shift = n,
// and multiply index by m
if !is_valid_immediate_scale(scale, alignment) {
let temp = make_temporary(f_context, offset.ty.clone(), vm);
......@@ -2233,7 +2237,8 @@ fn emit_mem_base(
base.clone() // trivial
} else {
let temp = make_temporary(f_context, pv.ty.clone(), vm);
emit_add_u64(backend, &temp, &base, (offset_val * scale as i64) as u64);
emit_add_u64(backend, &temp, &base,
(offset_val * scale as i64) as u64);
temp
}
} else {
......@@ -2241,10 +2246,12 @@ fn emit_mem_base(
// TODO: If scale == r*m (for some 0 <= m <= 4), multiply offset by r
// then use and add_ext(,...,m)
if scale.is_power_of_two() && is_valid_immediate_extension(log2(scale)) {
if scale.is_power_of_two() &&
is_valid_immediate_extension(log2(scale)) {
let temp = make_temporary(f_context, pv.ty.clone(), vm);
// temp = base + offset << log2(scale)
backend.emit_add_ext(&temp, &base, &offset, signed, log2(scale) as u8);
backend.emit_add_ext(&temp, &base, &offset, signed,
log2(scale) as u8);
temp
} else {
let temp_offset = make_temporary(f_context, offset.ty.clone(), vm);
......@@ -2278,7 +2285,8 @@ fn emit_mem_base(
emit_add_u64(backend, &temp, &base, offset as u64);
temp
}
} else if RegGroup::get_from_value(&offset) == RegGroup::GPR && offset.is_reg() {
} else if RegGroup::get_from_value(&offset) == RegGroup::GPR &&
offset.is_reg() {
let temp = make_temporary(f_context, pv.ty.clone(), vm);
backend.emit_add_ext(&temp, &base, &offset, signed, shift);
temp
......@@ -2331,7 +2339,8 @@ pub fn emit_addr_sym(backend: &mut CodeGenerator, dest: &P<Value>, src: &P<Value
// Set dest to be the page address of the entry for src in the GOT
backend.emit_adrp(&dest, &src);
// Note: The offset should always be a valid immediate offset as it is 12-bits
// Note: The offset should always be a valid immediate offset
// as it is 12-bits
// (The same size as an immediate offset)