GitLab will be upgraded on June 2nd 2020 at 2.00 pm (AEDT) to 3.00 pm (AEDT) due to Critical Security Patch Availability. During the update, GitLab and Mattermost services will not be available. If you have any concerns with this, please talk to local Gitlab admin team.

Commit c3ba71ac authored by John Zhang's avatar John Zhang

Merge branch 'master' into ci-script

parents 00c57362 a241c754
**/target/*
**/__pycache__/*
**/.cache/*
emit/*
**/temp/*
Cargo.lock
......
......@@ -35,21 +35,21 @@ test:cargo:api:
dependencies:
- build_test
script:
- RUST_BACKTRACE=1 CC=clang cargo test test_api
- RUST_BACKTRACE=1 RUST_TEST_THREADS=1 CC=clang cargo test test_api
test:cargo:ir:
stage: test
dependencies:
- build_test
script:
- RUST_BACKTRACE=1 CC=clang cargo test test_ir
- RUST_BACKTRACE=1 RUST_TEST_THREADS=1 CC=clang cargo test test_ir
test:cargo:compiler:
stage: test
dependencies:
- build_test
script:
- RUST_BACKTRACE=1 CC=clang cargo test test_compiler
- RUST_BACKTRACE=1 RUST_TEST_THREADS=1 CC=clang cargo test test_compiler
test:cargo:runtime:
stage: test
......@@ -63,18 +63,27 @@ testjit:milestones:
dependencies:
- build_test
script:
- RUST_BACKTRACE=1 pytest tests/test_jit/test_milestones.py
- RUST_BACKTRACE=1 RUST_TEST_THREADS=1 CC=clang cargo build 2>/dev/null
- RUST_BACKTRACE=1 pytest tests/test_jit/test_milestones.py
testjit:binops:
stage: test
dependencies:
- build_test
script:
- RUST_BACKTRACE=1 pytest tests/test_jit/test_binops.py
- RUST_BACKTRACE=1 RUST_TEST_THREADS=1 CC=clang cargo build 2>/dev/null
- RUST_BACKTRACE=1 pytest tests/test_jit/test_binops.py
testjit:cmpops:
stage: test
dependencies:
- build_test
script:
- RUST_BACKTRACE=1 pytest tests/test_jit/test_cmpops.py
- RUST_BACKTRACE=1 RUST_TEST_THREADS=1 CC=clang cargo build 2>/dev/null
- RUST_BACKTRACE=1 pytest tests/test_jit/test_cmpops.py
testjit:cmpops:
stage: test
script:
- RUST_BACKTRACE=1 RUST_TEST_THREADS=1 CC=clang cargo build 2>/dev/null
- RUST_BACKTRACE=1 pytest tests/test_jit/test_convops.py
\ No newline at end of file
......@@ -64,6 +64,8 @@ echo "KERNEL: $KERNEL"
echo "ARCH: $MACH"
echo "---------"
rm emit/*
if [ "$OS" == "linux" ]; then
RUSTFLAGS=-Zincremental=target/incr-cache RUST_BACKTRACE=1 RUST_TEST_THREADS=1 CC=clang-3.8 cargo test "$@"
elif [ "$OS" == "Darwin" ]; then
......
......@@ -91,6 +91,12 @@ pub enum Instruction_ {
BinOp(BinOp, OpIndex, OpIndex),
CmpOp(CmpOp, OpIndex, OpIndex),
ConvOp{
operation: ConvOp,
from_ty: P<MuType>,
to_ty: P<MuType>,
operand: OpIndex
},
// yields a tuple of results from the call
ExprCall{
......@@ -254,6 +260,9 @@ impl Instruction_ {
match self {
&Instruction_::BinOp(op, op1, op2) => format!("{:?} {} {}", op, ops[op1], ops[op2]),
&Instruction_::CmpOp(op, op1, op2) => format!("{:?} {} {}", op, ops[op1], ops[op2]),
&Instruction_::ConvOp{operation, ref from_ty, ref to_ty, operand} => {
format!("{:?} {} {} {}", operation, from_ty, to_ty, ops[operand])
}
&Instruction_::ExprCall{ref data, is_abort} => {
let abort = select_value!(is_abort, "ABORT_ON_EXN", "RETHROW");
format!("CALL {} {}", data.debug_str(ops), abort)
......
......@@ -4,6 +4,7 @@ use inst::*;
use op::*;
use utils::vec_utils;
use utils::Address;
use std::collections::HashMap;
use std::fmt;
......@@ -735,6 +736,8 @@ pub enum Constant {
FuncRef(MuID),
UFuncRef(MuID),
Vector(Vec<Constant>),
//Pointer(Address),
NullRef,
}
impl fmt::Display for Constant {
......@@ -756,6 +759,7 @@ impl fmt::Display for Constant {
}
write!(f, "]")
}
&Constant::NullRef => write!(f, "NullRef"),
}
}
}
......
......@@ -5,6 +5,7 @@ pub fn is_terminal_inst(inst: &Instruction_) -> bool {
match inst {
&BinOp(_, _, _)
| &CmpOp(_, _, _)
| &ConvOp{..}
| &ExprCall{..}
| &Load{..}
| &Store{..}
......@@ -49,6 +50,7 @@ pub fn has_side_effect(inst: &Instruction_) -> bool {
match inst {
&BinOp(_, _, _) => false,
&CmpOp(_, _, _) => false,
&ConvOp{..} => false,
&ExprCall{..} => true,
&Load{..} => true,
&Store{..} => true,
......
......@@ -35,6 +35,7 @@ pub enum OpCode {
// expression
Binary(BinOp),
Comparison(CmpOp),
Conversion(ConvOp),
AtomicRMW(AtomicRMWOp),
ExprCall,
......@@ -172,6 +173,22 @@ pub enum CmpOp {
FUNO
}
#[derive(Copy, Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)]
pub enum ConvOp {
TRUNC,
ZEXT,
SEXT,
FPTRUNC,
FPEXT,
FPTOUI,
FPTOSI,
UITOFP,
SITOFP,
BITCAST,
REFCAST,
PTRCAST
}
#[derive(Copy, Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)]
pub enum AtomicRMWOp {
XCHG,
......@@ -207,6 +224,7 @@ pub fn pick_op_code_for_inst(inst: &Instruction) -> OpCode {
match inst.v {
Instruction_::BinOp(op, _, _) => OpCode::Binary(op),
Instruction_::CmpOp(op, _, _) => OpCode::Comparison(op),
Instruction_::ConvOp{operation, ..} => OpCode::Conversion(operation),
Instruction_::AtomicRMW{op, ..} => OpCode::AtomicRMW(op),
Instruction_::ExprCall{..} => OpCode::ExprCall,
Instruction_::Load{..} => OpCode::Load,
......
......@@ -12,6 +12,14 @@ lazy_static! {
pub static ref ADDRESS_TYPE : P<MuType> = P(
MuType::new(new_internal_id(), MuType_::int(POINTER_SIZE * 8))
);
pub static ref UINT8_TYPE : P<MuType> = P(
MuType::new(new_internal_id(), MuType_::int(8))
);
pub static ref UINT16_TYPE : P<MuType> = P(
MuType::new(new_internal_id(), MuType_::int(16))
);
pub static ref UINT32_TYPE : P<MuType> = P(
MuType::new(new_internal_id(), MuType_::int(32))
......@@ -27,6 +35,8 @@ lazy_static! {
pub static ref INTERNAL_TYPES : Vec<P<MuType>> = vec![
ADDRESS_TYPE.clone(),
UINT8_TYPE.clone(),
UINT16_TYPE.clone(),
UINT32_TYPE.clone(),
UINT64_TYPE.clone(),
DOUBLE_TYPE.clone()
......
This diff is collapsed.
......@@ -62,14 +62,14 @@ lazy_static! {
pub static ref R13 : P<Value> = GPR!(13,"r13");
pub static ref R14 : P<Value> = GPR!(14,"r14");
pub static ref R15 : P<Value> = GPR!(15,"r15");
pub static ref RIP : P<Value> = GPR!(32,"rip");
pub static ref RETURN_GPRs : [P<Value>; 2] = [
RAX.clone(),
RDX.clone(),
];
pub static ref ARGUMENT_GPRs : [P<Value>; 6] = [
RDI.clone(),
RSI.clone(),
......@@ -78,7 +78,7 @@ lazy_static! {
R8.clone(),
R9.clone()
];
pub static ref CALLEE_SAVED_GPRs : [P<Value>; 6] = [
RBX.clone(),
RBP.clone(),
......@@ -99,7 +99,7 @@ lazy_static! {
R10.clone(),
R11.clone()
];
pub static ref ALL_GPRs : [P<Value>; 15] = [
RAX.clone(),
RCX.clone(),
......@@ -136,13 +136,13 @@ lazy_static!{
pub static ref XMM12 : P<Value> = FPR!(28,"xmm12");
pub static ref XMM13 : P<Value> = FPR!(29,"xmm13");
pub static ref XMM14 : P<Value> = FPR!(30,"xmm14");
pub static ref XMM15 : P<Value> = FPR!(31,"xmm15");
pub static ref XMM15 : P<Value> = FPR!(31,"xmm15");
pub static ref RETURN_FPRs : [P<Value>; 2] = [
XMM0.clone(),
XMM1.clone()
];
pub static ref ARGUMENT_FPRs : [P<Value>; 8] = [
XMM0.clone(),
XMM1.clone(),
......@@ -153,7 +153,7 @@ lazy_static!{
XMM6.clone(),
XMM7.clone()
];
pub static ref CALLEE_SAVED_FPRs : [P<Value>; 0] = [];
pub static ref CALLER_SAVED_FPRs : [P<Value>; 16] = [
......@@ -174,7 +174,7 @@ lazy_static!{
XMM14.clone(),
XMM15.clone(),
];
pub static ref ALL_FPRs : [P<Value>; 16] = [
XMM0.clone(),
XMM1.clone(),
......@@ -234,10 +234,10 @@ lazy_static! {
map.insert(XMM14.id(), XMM14.clone());
map.insert(XMM15.id(), XMM15.clone());
map.insert(RIP.id(), RIP.clone());
map
};
// put caller saved regs first (they imposes no overhead if there is no call instruction)
pub static ref ALL_USABLE_MACHINE_REGs : Vec<P<Value>> = vec![
RAX.clone(),
......@@ -279,7 +279,7 @@ pub fn init_machine_regs_for_func (func_context: &mut FunctionContext) {
for reg in ALL_MACHINE_REGs.values() {
let reg_id = reg.extract_ssa_id().unwrap();
let entry = SSAVarEntry::new(reg.clone());
func_context.values.insert(reg_id, entry);
}
}
......@@ -320,8 +320,8 @@ pub fn is_callee_saved(reg_id: MuID) -> bool {
return true;
}
}
false
false
}
pub fn is_valid_x86_imm(op: &P<Value>) -> bool {
......@@ -332,4 +332,4 @@ pub fn is_valid_x86_imm(op: &P<Value>) -> bool {
},
_ => false
}
}
}
\ No newline at end of file
......@@ -171,3 +171,30 @@ pub struct BackendTypeInfo {
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
pub enum RegGroup {GPR, FPR}
impl RegGroup {
pub fn get(ty: &P<MuType>) -> RegGroup {
match ty.v {
// for now, only use 64bits registers
MuType_::Int(len) if len == 8 => RegGroup::GPR,
MuType_::Int(len) if len == 16 => RegGroup::GPR,
MuType_::Int(len) if len == 32 => RegGroup::GPR,
MuType_::Int(len) if len == 64 => RegGroup::GPR,
MuType_::Ref(_)
| MuType_::IRef(_)
| MuType_::WeakRef(_)
| MuType_::UPtr(_)
| MuType_::ThreadRef
| MuType_::StackRef
| MuType_::Tagref64
| MuType_::FuncRef(_)
| MuType_::UFuncPtr(_) => RegGroup::GPR,
MuType_::Float => RegGroup::FPR,
MuType_::Double => RegGroup::FPR,
_ => unimplemented!()
}
}
}
\ No newline at end of file
......@@ -54,18 +54,7 @@ impl InterferenceGraph {
self.nodes.insert(reg_id, node.clone());
// add node property
let group = {
let ref ty = entry.ty();
if types::is_scalar(ty) {
if types::is_fp(ty) {
backend::RegGroup::FPR
} else {
backend::RegGroup::GPR
}
} else {
unimplemented!()
}
};
let group = backend::RegGroup::get(entry.ty());
let property = NodeProperty {
color: None,
group: group,
......
......@@ -138,5 +138,28 @@ pub fn link_dylib (funcs: Vec<MuName>, out: &str) -> PathBuf {
let mut out_path = PathBuf::from(backend::AOT_EMIT_DIR);
out_path.push(out);
link_dylib_internal(files, out_path)
}
pub fn link_dylib_with_extra_srcs(funcs: Vec<MuName>, srcs: Vec<String>, out: &str) -> PathBuf{
let files = {
let mut ret = vec![];
for func in funcs {
ret.push(get_path_for_mu_func(func));
}
for src in srcs {
ret.push(PathBuf::from(src));
}
ret.push(get_path_for_mu_context());
ret
};
let mut out_path = PathBuf::from(backend::AOT_EMIT_DIR);
out_path.push(out);
link_dylib_internal(files, out_path)
}
\ No newline at end of file
......@@ -24,13 +24,18 @@ pub fn get_test_clang_path() -> String {
pub fn exec (mut cmd: Command) -> Output {
println!("executing: {:?}", cmd);
let output = cmd.output().expect("failed to execute");
let output = match cmd.output() {
Ok(res) => res,
Err(e) => panic!("failed to execute: {}", e)
};
println!("---out---");
println!("{}", String::from_utf8_lossy(&output.stdout));
println!("---err---");
println!("{}", String::from_utf8_lossy(&output.stderr));
assert!(output.status.success());
output
}
......
......@@ -243,11 +243,13 @@ extern fn _forwarder__MuVM__set_trap_handler(mvm: *mut CMuVM, trap_handler: CMuT
};
}
extern fn _forwarder__MuVM__compile_to_sharedlib(mvm: *mut CMuVM, lib_name: CMuCString) {
extern fn _forwarder__MuVM__compile_to_sharedlib(mvm: *mut CMuVM, lib_name: CMuCString,
extra_srcs: *const CMuCString, n: usize) {
let mut _arg_mvm = from_MuVM_ptr(mvm);
let mut _arg_lib_name = from_MuCString(lib_name);
let _arg_extra_srcs = from_MuCString_array(extra_srcs, n);
unsafe {
(*_arg_mvm).compile_to_sharedlib(&_arg_lib_name)
(*_arg_mvm).compile_to_sharedlib(&_arg_lib_name, _arg_extra_srcs)
};
}
......
......@@ -110,7 +110,7 @@ pub struct CMuVM {
pub name_of: extern fn(*mut CMuVM, CMuID) -> CMuName,
pub set_trap_handler: extern fn(*mut CMuVM, CMuTrapHandler, CMuCPtr),
// this function is only used in testing jit
pub compile_to_sharedlib: extern fn(*mut CMuVM, CMuCString),
pub compile_to_sharedlib: extern fn(*mut CMuVM, CMuCString, *const CMuCString, CMuArraySize),
}
#[repr(C)]
......
......@@ -42,7 +42,10 @@ pub enum NodeType {
TypeStruct { id: MuID, fieldtys: Vec<MuTypeNode> },
TypeHybrid { id: MuID, fixedtys: Vec<MuTypeNode>, varty: MuTypeNode },
TypeArray { id: MuID, elemty: MuTypeNode, len: usize },
TypeVector { id: MuID, elemty: MuTypeNode, lem: usize },
TypeVector { id: MuID, elemty: MuTypeNode, len: usize },
TypeVoid { id: MuID },
TypeTagRef64 { id: MuID },
TypeRef { id: MuID, ty: MuTypeNode },
TypeIRef { id: MuID, ty: MuTypeNode },
......
This diff is collapsed.
......@@ -70,7 +70,7 @@ impl MuVM {
panic!("Not implemented")
}
pub fn compile_to_sharedlib(&self, lib_name: &str) {
pub fn compile_to_sharedlib(&self, lib_name: &str, extra_srcs: Vec<String>) {
extern crate libloading as ll;
use compiler::*;
......@@ -88,7 +88,7 @@ impl MuVM {
func_names.push(func.name().unwrap());
}
backend::emit_context(&self.vm);
aot::link_dylib(func_names, lib_name);
aot::link_dylib_with_extra_srcs(func_names, extra_srcs, lib_name);
}
}
......
......@@ -271,7 +271,7 @@ struct MuVM {
// Set handlers
void (*set_trap_handler)(MuVM *mvm, MuTrapHandler trap_handler, MuCPtr userdata);
void (*compile_to_sharedlib)(MuVM *mvm, MuCString lib_name);
void (*compile_to_sharedlib)(MuVM *mvm, MuCString lib_name, MuCString *extra_srcs, MuArraySize n_extra_srcs); /// MUAPIPARSER extra_srcs:array:n_extra_srcs
};
// A local context. It can only be used by one thread at a time. It holds many
......
......@@ -478,6 +478,15 @@ impl <'a> VM {
funcs.insert(func.id(), RwLock::new(func));
}
/// The IR builder needs to look-up the function signature from the existing function ID.
pub fn get_func_sig_for_func(&self, id: MuID) -> P<MuFuncSig> {
let funcs_lock = self.funcs.read().unwrap();
match funcs_lock.get(&id) {
Some(func) => func.read().unwrap().sig.clone(),
None => panic!("cannot find Mu function #{}", id)
}
}
pub fn define_func_version (&self, func_ver: MuFunctionVersion) {
info!("define function version {}", func_ver);
// record this version
......@@ -501,6 +510,72 @@ impl <'a> VM {
// redefinition happens here
// do stuff
}
/// Add a new bundle into VM.
///
/// This function will drain the contents of all arguments.
///
/// Ideally, this function should happen atomically. e.g. The client should not see a new type
/// added without also seeing a new function added.
pub fn declare_many(&self,
new_id_name_map: &mut HashMap<MuID, MuName>,
new_types: &mut HashMap<MuID, P<MuType>>,
new_func_sigs: &mut HashMap<MuID, P<MuFuncSig>>,
new_constants: &mut HashMap<MuID, P<Value>>,
new_globals: &mut HashMap<MuID, P<Value>>,
new_funcs: &mut HashMap<MuID, Box<MuFunction>>,
new_func_vers: &mut HashMap<MuID, Box<MuFunctionVersion>>
) {
// Make sure other components, if ever acquiring multiple locks at the same time, acquire
// them in this order, to prevent deadlock.
let mut id_name_map = self.id_name_map.write().unwrap();
let mut name_id_map = self.name_id_map.write().unwrap();
let mut types = self.types.write().unwrap();
let mut constants = self.constants.write().unwrap();
let mut globals = self.globals.write().unwrap();
let mut func_sigs = self.func_sigs.write().unwrap();
let mut funcs = self.funcs.write().unwrap();
let mut func_vers = self.func_vers.write().unwrap();
for (id, name) in new_id_name_map.drain() {
id_name_map.insert(id, name.clone());
name_id_map.insert(name, id);
}
for (id, obj) in new_types.drain() {
types.insert(id, obj);
}
for (id, obj) in new_constants.drain() {
constants.insert(id, obj);
}
for (id, obj) in new_globals.drain() {
globals.insert(id, obj);
}
for (id, obj) in new_func_sigs.drain() {
func_sigs.insert(id, obj);
}
for (id, obj) in new_funcs.drain() {
funcs.insert(id, RwLock::new(*obj));
}
for (id, obj) in new_func_vers.drain() {
let func_id = obj.func_id;
func_vers.insert(id, RwLock::new(*obj));
{
trace!("Adding funcver {} as a version of {}...", id, func_id);
let func = funcs.get_mut(&func_id).unwrap();
func.write().unwrap().new_version(id);
trace!("Added funcver {} as a version of {} {:?}.", id, func_id, func);
}
}
// Locks released here
}
pub fn add_compiled_func (&self, func: CompiledFunction) {
debug_assert!(self.funcs.read().unwrap().contains_key(&func.func_id));
......
......@@ -173,5 +173,175 @@ fn sdiv() -> VM {
vm.define_func_version(func_ver);
vm
}
#[test]
fn test_shl() {
let lib = testutil::compile_fnc("shl", &shl);
unsafe {
let shl : libloading::Symbol<unsafe extern fn(u64, u8) -> u64> = lib.get(b"shl").unwrap();
let shl_1_2 = shl(1, 2);
println!("shl(1, 2) = {}", shl_1_2);
assert!(shl_1_2 == 4);
let shl_2_2 = shl(2, 2);
println!("shl(2, 2) = {}", shl_2_2);
assert!(shl_2_2 == 8);
}
}
fn shl() -> VM {
let vm = VM::new();
// .typedef @int64 = int<64>
let type_def_int64 = vm.declare_type(vm.next_id(), MuType_::int(64));
vm.set_name(type_def_int64.as_entity(), Mu("int64"));
// .typedef @int8 = int<8>
let type_def_int8 = vm.declare_type(vm.next_id(), MuType_::int(8));
vm.set_name(type_def_int8.as_entity(), Mu("int8"));
// .funcsig @shl_sig = (@int64 @int8) -> (@int64)
let shl_sig = vm.declare_func_sig(vm.next_id(), vec![type_def_int64.clone()], vec![type_def_int64.clone(), type_def_int8.clone()]);
vm.set_name(shl_sig.as_entity(), Mu("shl_sig"));
// .funcdecl @shl <@shl_sig>
let func_id = vm.next_id();
let func = MuFunction::new(func_id, shl_sig.clone());
vm.set_name(func.as_entity(), Mu("shl"));
vm.declare_func(func);
// .funcdef @shl VERSION @shl_v1 <@shl_sig>
let mut func_ver = MuFunctionVersion::new(vm.next_id(), func_id, shl_sig.clone());
vm.set_name(func_ver.as_entity(), Mu("shl_v1"));
// %entry(<@int64> %a, <@int8> %b):
let mut blk_entry = Block::new(vm.next_id());
vm.set_name(blk_entry.as_entity(), Mu("entry"));
let blk_entry_a = func_ver.new_ssa(vm.next_id(), type_def_int64.clone());
vm.set_name(blk_entry_a.as_entity(), Mu("blk_entry_a"));
let blk_entry_b = func_ver.new_ssa(vm.next_id(), type_def_int8.clone());
vm.set_name(blk_entry_b.as_entity(), Mu("blk_entry_b"));
// %r = SHL %a %b
let blk_entry_r = func_ver.new_ssa(vm.next_id(), type_def_int64.clone());
vm.set_name(blk_entry_r.as_entity(), Mu("blk_entry_r"));
let blk_entry_add = func_ver.new_inst(Instruction{
hdr: MuEntityHeader::unnamed(vm.next_id()),
value: Some(vec![blk_entry_r.clone_value()]),
ops: RwLock::new(vec![blk_entry_a.clone(), blk_entry_b.clone()]),
v: Instruction_::BinOp(BinOp::Shl, 0, 1)
});
// RET %r
let blk_entry_term = func_ver.new_inst(Instruction{
hdr: MuEntityHeader::unnamed(vm.next_id()),
value: None,
ops: RwLock::new(vec![blk_entry_r.clone()]),
v: Instruction_::Return(vec![0])
});
blk_entry.content = Some(BlockContent{
args: vec![blk_entry_a.clone_value(), blk_entry_b.clone_value()],
exn_arg: None,
body: vec![blk_entry_add, blk_entry_term],
keepalives: None
});
func_ver.define(FunctionContent{
entry: blk_entry.id(),
blocks: hashmap!{
blk_entry.id() => blk_entry
}
});
vm.define_func_version(func_ver);
vm
}
#[test]
fn test_lshr() {
let lib = testutil::compile_fnc("lshr", &lshr);
unsafe {
let lshr : libloading::Symbol<unsafe extern fn(u64, u8) -> u64> = lib.get(b"lshr").unwrap();
let lshr_8_3 = lshr(8, 3);
println!("lshr(8, 3) = {}", lshr_8_3);
assert!(lshr_8_3 == 1);
}
}
fn lshr() -> VM {
let vm = VM::new();
// .typedef @int64 = int<64>
let type_def_int64 = vm.declare_type(vm.next_id(), MuType_::int(64));
vm.set_name(type_def_int64.as_entity(), Mu("int64"));
// .typedef @int8 = int<8>
let type_def_int8 = vm.declare_type(vm.next_id(), MuType_::int(8));
vm.set_name(type_def_int8.as_entity(), Mu("int8"));
// .funcsig @lshr_sig = (@int64 @int8) -> (@int64)
let lshr_sig = vm.declare_func_sig(vm.next_id(), vec![type_def_int64.clone()], vec![type_def_int64.clone(), type_def_int8.clone()]);
vm.set_name(lshr_sig.as_entity(), Mu("lshr_sig"));
// .funcdecl @lshr <@lshr_sig>
let func_id = vm.next_id();
let func = MuFunction::new(func_id, lshr_sig.clone());
vm.set_name(func.as_entity(), Mu("lshr"));
vm.declare_func(func);
// .funcdef @lshr VERSION @lshr_v1 <@lshr_sig>
let mut func_ver = MuFunctionVersion::new(vm.next_id(), func_id, lshr_sig.clone());
vm.set_name(func_ver.as_entity(), Mu("lshr_v1"));
// %entry(<@int64> %a, <@int8> %b):
let mut blk_entry = Block::new(vm.next_id());
vm.set_name(blk_entry.as_entity(), Mu("entry"));