Commit d9196658 authored by Isaac Oscar Gariano's avatar Isaac Oscar Gariano

Updated ALLOCA implementation

parent c0089a9f
......@@ -69,6 +69,10 @@ lazy_static! {
MuType::new(new_internal_id(), MuType_::muref(VOID_TYPE.clone()))
);
pub static ref IREF_VOID_TYPE : P<MuType> = P(
MuType::new(new_internal_id(), MuType_::iref(VOID_TYPE.clone()))
);
pub static ref INTERNAL_TYPES : Vec<P<MuType>> = vec![
ADDRESS_TYPE.clone(),
UINT1_TYPE.clone(),
......@@ -82,6 +86,7 @@ lazy_static! {
FLOAT_TYPE.clone(),
VOID_TYPE.clone(),
REF_VOID_TYPE.clone(),
IREF_VOID_TYPE.clone(),
];
}
......
......@@ -2035,59 +2035,6 @@ impl CodeGenerator for ASMCodeGen {
self.cur().blocks.contains_key(&block_name)
}
fn set_block_livein(&mut self, block_name: MuName, live_in: &Vec<P<Value>>) {
let cur = self.cur_mut();
match cur.blocks.get_mut(&block_name) {
Some(ref mut block) => {
if block.livein.is_empty() {
let mut live_in = {
let mut ret = vec![];
for p in live_in {
match p.extract_ssa_id() {
Some(id) => ret.push(id),
// this should not happen
None => error!("{} as live-in of block {} is not SSA", p, block_name)
}
}
ret
};
block.livein.append(&mut live_in);
} else {
panic!("seems we are inserting livein to block {} twice", block_name);
}
}
None => panic!("haven't created ASMBlock for {}", block_name)
}
}
fn set_block_liveout(&mut self, block_name: MuName, live_out: &Vec<P<Value>>) {
let cur = self.cur_mut();
match cur.blocks.get_mut(&block_name) {
Some(ref mut block) => {
if block.liveout.is_empty() {
let mut live_out = {
let mut ret = vec![];
for p in live_out {
match p.extract_ssa_id() {
Some(id) => ret.push(id),
// the liveout are actually args out of this block
// (they can be constants)
None => trace!("{} as live-out of block {} is not SSA", p, block_name)
}
}
ret
};
block.liveout.append(&mut live_out);
} else {
panic!("seems we are inserting liveout to block {} twice", block_name);
}
}
None => panic!("haven't created ASMBlock for {}", block_name)
}
}
fn add_cfi_sections(&mut self, arg: &str) { self.add_asm_symbolic(format!(".cfi_sections {}", arg)); }
fn add_cfi_startproc(&mut self) {
self.add_asm_symbolic(".cfi_startproc".to_string());
......@@ -2127,6 +2074,22 @@ impl CodeGenerator for ASMCodeGen {
)
}
fn emit_frame_shrink(&mut self) {
trace!("emit: \tframe shrink");
let asm = format!("ADD SP,SP,#{}", FRAME_SIZE_PLACEHOLDER.clone());
let line = self.line();
self.cur_mut().add_frame_size_patchpoint(ASMLocation::new(line, 11, FRAME_SIZE_PLACEHOLDER_LEN, 0));
self.add_asm_inst(
asm,
linked_hashmap!{},
linked_hashmap!{},
false
)
}
fn emit_add_str(&mut self, dest: Reg, src1: Reg, src2: &str) {self.internal_binop_str("ADD", dest, src1, src2)}
// Pushes a pair of registers on the givne stack (uses the STP instruction)
......@@ -2174,7 +2137,12 @@ impl CodeGenerator for ASMCodeGen {
self.add_asm_inst_internal(asm, linked_hashmap!{}, linked_hashmap!{id1 => vec![loc1]}, false, ASMBranchTarget::Return, None);
}
#[cfg(target_os = "linux")]
fn emit_fake_ret(&mut self) {
trace!("emit: \tFAKE RET");
let asm = format!("B muentry_return");
self.add_asm_inst_internal(asm, linked_hashmap!{}, linked_hashmap!{}, false, ASMBranchTarget::Return, None);
}
fn emit_bl(&mut self, callsite: String, func: MuName, pe: Option<MuName>, is_native: bool) -> ValueLocation {
if is_native {
trace!("emit: \tBL /*C*/ {}", func);
......
......@@ -12,7 +12,6 @@
// See the License for the specific language governing permissions and
// limitations under the License.
use ast::ptr::P;
use ast::ir::*;
use runtime::ValueLocation;
......@@ -20,6 +19,8 @@ use compiler::machine_code::MachineCode;
use compiler::backend::{Reg, Mem};
pub trait CodeGenerator {
fn emit_fake_ret(&mut self);
fn start_code(&mut self, func_name: MuName, entry: MuName) -> ValueLocation;
fn finish_code(&mut self, func_name: MuName) -> (Box<MachineCode + Sync + Send>, ValueLocation);
......@@ -32,8 +33,6 @@ pub trait CodeGenerator {
fn start_block(&mut self, block_name: MuName);
fn block_exists(&self, block_name: MuName) -> bool;
fn start_exception_block(&mut self, block_name: MuName) -> ValueLocation;
fn set_block_livein(&mut self, block_name: MuName, live_in: &Vec<P<Value>>);
fn set_block_liveout(&mut self, block_name: MuName, live_out: &Vec<P<Value>>);
fn end_block(&mut self, block_name: MuName);
// add CFI info
......@@ -49,6 +48,7 @@ pub trait CodeGenerator {
// emit code to adjust frame
fn emit_frame_grow(&mut self); // Emits a SUB
fn emit_frame_shrink(&mut self); // Emits an ADD
// Used to pass a string that the assembler will interpret as an immediate argument
// (This is neccesary to support the use of ELF relocations like ':tprel_hi12:foo')
......@@ -91,7 +91,6 @@ pub trait CodeGenerator {
fn emit_ldaxp(&mut self, dest1: Reg, dest2: Reg, src: Mem); // [base]
fn emit_ldnp(&mut self, dest1: Reg/*GPR or FPR*/, dest2: Reg/*GPR or FPR*/, src: Mem); // [base, #simm7]
// Stores
fn emit_str(&mut self, dest: Mem, src: Reg/*GPR or FPR*/); // supports the full full range of addressing modes
fn emit_sttr(&mut self, dest: Mem, src: Reg); // [base, #simm9]
......@@ -105,9 +104,7 @@ pub trait CodeGenerator {
fn emit_stlxp(&mut self, dest: Mem, status: Reg, src1: Reg, src2: Reg); // [base]
fn emit_stnp(&mut self, dest: Mem, src1: Reg/*GPR or FPR*/, src2: Reg/*GPR or FPR*/); // [base, #simm7]
// branching
// calls
// Calls
fn emit_bl(&mut self, callsite: String, func: MuName, pe: Option<MuName>, is_native: bool) -> ValueLocation;
fn emit_blr(&mut self, callsite: String, func: Reg, pe: Option<MuName>) -> ValueLocation;
......@@ -130,7 +127,7 @@ pub trait CodeGenerator {
fn emit_adrp(&mut self, dest: Reg, src: Reg);
// Unary ops
fn emit_mov(&mut self, dest: Reg, src: Reg);
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
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);
......@@ -148,7 +145,7 @@ pub trait CodeGenerator {
fn emit_rev16(&mut self, dest: Reg, src: Reg);
fn emit_rev32(&mut self, dest: Reg/*64*/, src: Reg);
fn emit_rev64(&mut self, dest: Reg/*64*/, src: Reg); // alias of REV
fn emit_fabs(&mut self, dest: Reg, src: Reg/*Must have different size*/);
fn emit_fabs(&mut self, dest: Reg, src: Reg);
fn emit_fcvt(&mut self, dest: Reg, src: Reg/*Must have different size*/);
fn emit_fcvtas(&mut self, dest: Reg/*GPR, may have different size*/, src: Reg);
fn emit_fcvtau(&mut self, dest: Reg/*GPR, may have different size*/, src: Reg);
......
This diff is collapsed.
......@@ -284,4 +284,16 @@ lazy_static! {
aot: ValueLocation::Relocatable(RegGroup::GPR, String::from("muentry_print_hex")),
jit: RwLock::new(None)
};
// impl/decl: mod.rs
pub static ref MEM_ZERO : RuntimeEntrypoint = RuntimeEntrypoint {
sig: P(MuFuncSig {
hdr: MuEntityHeader::unnamed(ir::new_internal_id()),
ret_tys: vec![],
arg_tys: vec![IREF_VOID_TYPE.clone(), UINT64_TYPE.clone()]
}),
aot: ValueLocation::Relocatable(RegGroup::GPR, String::from("muentry_mem_zero")),
jit: RwLock::new(None)
};
}
......@@ -197,4 +197,9 @@ pub extern fn mu_main(edata: *const(), dumped_vm : *mut Arc<VM>, argc: c_int, ar
#[allow(unreachable_code)]
pub extern fn muentry_print_hex(x: u64) {
println!("PRINTHEX: 0x{:x}", x);
}
#[no_mangle]
pub unsafe extern fn muentry_mem_zero(dest: *mut u8, size: usize) {
std::ptr::write_bytes(dest, 0, size);
}
\ No newline at end of file
......@@ -137,3 +137,9 @@ begin_func fake_swap_mu_thread
# return to caller, but preserve those pushed values (since THREADEXIT will pick them up)
RET
end_func fake_swap_mu_thread
begin_func muentry_return
MOV SP, FP
pop_pair FP, LR
RET LR
end_func muentry_return
# 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.
from util import execute, compile_bundle, load_bundle, get_function;
import pytest;
import ctypes;
# Tests that zebu can handle wierd, but valid mu names
def test_alloca():
lib = load_bundle(
"""
.typedef type = struct<int<64> double ref<void>>
.funcdef alloca <(int<64>)->(int<64>)>
{
entry(<int<64>>arg):
a = ALLOCA <type>
// Load the int field to ai_int
ai_ref = GETFIELDIREF <type 0> a
ai_int = LOAD <int<64>> ai_ref
// Load the double field to ad_int (converting it to an int<64>)
ad_ref = GETFIELDIREF <type 1> a
ad = LOAD <double> ad_ref
ad_int = BITCAST <double int<64>> ad
// Load the ref field to ar_int (which will be '0' for a null ref, and '1' otherwise)
ar_ref = GETFIELDIREF <type 2> a
ar = LOAD <ref<void>> ar_ref
ar_null = NE <ref<void>> ar <ref<void>>NULL
ar_int = ZEXT <int<1> int<64>> ar_null
// Store arg into the ALLOCA'd area
STORE <type> ai_ref arg
argc_int = LOAD <int<64>> ai_ref
// sum all the *_int values togterh
res_0 = ADD <int<64>> ai_int ad_int
res_1 = ADD <int<64>> res_0 ar_int
res_2 = ADD <int<64>> res_1 argc_int
RET res_2
}
""", "test_alloca");
alloca = get_function(lib.alloca, [ctypes.c_int64], ctypes.c_int64);
assert(alloca(-56) == -56);
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment