WARNING! Access to this system is limited to authorised users only.
Unauthorised users may be subject to prosecution.
Unauthorised access to this system is a criminal offence under Australian law (Federal Crimes Act 1914 Part VIA)
It is a criminal offence to:
(1) Obtain access to data without authority. -Penalty 2 years imprisonment.
(2) Damage, delete, alter or insert data without authority. -Penalty 10 years imprisonment.
User activity is monitored and recorded. Anyone using this system expressly consents to such monitoring and recording.

To protect your data, the CISO officer has suggested users to enable 2FA as soon as possible.
Currently 2.7% of users enabled 2FA.

Commit 4228dc95 authored by Eduardo Souza's avatar Eduardo Souza
Browse files

passing all tests

parent a1cb83e3
def seq (x y) y;
def foo(x)
seq(x = 10 x)
foo(4)
\ No newline at end of file
def plusone(x)
var y = x in
y + 1
plusone(3)
\ No newline at end of file
def seq(x y)
y
def pow(x y)
var total = x in
seq(for i = 1, i < y in
total = total * x
total )
pow (3 2)
\ No newline at end of file
def seq(x y)
y
def fibi(x)
var a = 1, b = 1, c in
seq (( for i = 2, i < x in
seq (c = a + b seq (a = b b = c)))
b) ;
fibi(10)
\ No newline at end of file
def foo(x)
for i = 1, i < x, 1.0 in
x+1;
foo(5)
\ No newline at end of file
use crate::generator::{Context, create_block_alloca};
use crate::generator::{create_block_alloca, Context};
use crate::mu_generator::*;
use llvm_sys::core::*;
use llvm_sys::prelude::LLVMValueRef;
......@@ -10,6 +10,7 @@ use std::os::raw::{c_char, c_double, c_uint};
#[macro_use]
use crate::ir_macros;
use mu::ast::inst::*;
use mu::ast::ir::*;
use mu::ast::op::BinOp::{FAdd, FMul, FSub, Udiv};
......@@ -283,7 +284,7 @@ impl Exp for VarExp {
let mut assigned_exps = vec![];
for (var, exp) in &self.vars {
assigned_exps.push(format!("Assign({}, {})", var.print(), exp.print()));
};
}
format!("VarExp({:?}, {})", assigned_exps, self.body_exp.print())
}
......@@ -292,7 +293,43 @@ impl Exp for VarExp {
module: &*mut LLVMModule,
context: &mut Context,
) -> Result<*mut LLVMValue, String> {
unimplemented!()
let mut old_bindings = vec![];
let llvm_block = LLVMGetInsertBlock(context.builder);
for var in &self.vars {
let (name, init_expr) = var;
let init_value: *mut LLVMValue = match init_expr.code_gen(module, context) {
Ok(result) => result,
e @ Err(_) => return e,
};
let variable = create_block_alloca(context, llvm_block, name.name.as_str());
LLVMBuildStore(context.builder, init_value, variable);
old_bindings.push(context.named_values.remove(name.name.as_str()));
context.named_values.insert(name.name.clone(), variable);
}
let body_value: *mut LLVMValue = match self.body_exp.code_gen(module, context) {
Ok(result) => result,
e @ Err(_) => return e,
};
let mut old_bindings_iter = old_bindings.iter();
for var in &self.vars {
let (name, _) = var;
context.named_values.remove(name.name.as_str());
match old_bindings_iter.next() {
Some(&Some(value)) => {
context.named_values.insert(name.name.clone(), value);
}
_ => (),
}
}
Ok(body_value)
}
unsafe fn code_gen_mu(
......@@ -300,7 +337,43 @@ impl Exp for VarExp {
vm: &mut Mu_VM,
fun_ver: &mut MuFunctionVersion,
) -> Result<Arc<TreeNode>, String> {
unimplemented!()
let mut old_bindings = vec![];
for var in &self.vars {
let (name, init_expr) = var;
let start_exp = match init_expr.code_gen_mu(vm, fun_ver) {
Ok(r) => r,
e @ Err(_) => return e,
};
let current_block = vm.blocks_map.get_mut(&vm.curr_block).unwrap();
old_bindings.push(current_block.form_args.remove(name.name.as_str()));
current_block.form_args.insert(name.name.clone(), start_exp);
}
let body_value = match self.body_exp.code_gen_mu(vm, fun_ver) {
Ok(r) => r,
e @ Err(_) => return e,
};
let mut old_bindings_iter = old_bindings.into_iter();
for var in &self.vars {
let (name, _) = var;
let current_block = vm.blocks_map.get_mut(&vm.curr_block).unwrap();
current_block.form_args.remove(name.name.as_str());
match old_bindings_iter.next() {
Some(Some(value)) => {
current_block.form_args.insert(name.name.clone(), value);
}
_ => (),
}
}
Ok(body_value)
}
}
......@@ -334,27 +407,17 @@ impl Exp for ForExp {
"preloop\0".as_ptr() as *const c_char,
);
let variable =
create_block_alloca(context, preheader_block, self.var.name.clone().as_str());
LLVMBuildStore(context.builder, start_exp, variable);
LLVMBuildBr(context.builder, preloop_block);
LLVMPositionBuilderAtEnd(context.builder, preloop_block);
// let mut phi = LLVMBuildPhi(
// context.builder,
// context.ty,
// self.var.name().as_str().as_ptr() as *const c_char,
// );
//
// LLVMAddIncoming(
// phi,
// vec![start_exp].as_mut_slice().as_mut_ptr(),
// vec![preheader_block].as_mut_slice().as_mut_ptr(),
// 1 as c_uint,
// );
let variable = create_block_alloca(context, preheader_block, self.var.name.clone().as_str());
LLVMBuildStore(context.builder,start_exp, variable);
let old_value = context.named_values.remove(self.var.name());
context.named_values.insert(self.var.name().clone(), variable);
context
.named_values
.insert(self.var.name().clone(), variable);
let end_exp: *mut LLVMValue = match self.end_exp().code_gen(module, context) {
Ok(result) => result,
......@@ -394,7 +457,11 @@ impl Exp for ForExp {
e @ Err(_) => return e,
};
let cur_value = LLVMBuildLoad(context.builder,variable, self.var.name.clone().as_str().as_ptr() as *const c_char);
let cur_value = LLVMBuildLoad(
context.builder,
variable,
self.var.name.clone().as_str().as_ptr() as *const c_char,
);
let next_value = LLVMBuildFAdd(
context.builder,
cur_value,
......@@ -404,12 +471,6 @@ impl Exp for ForExp {
LLVMBuildStore(context.builder, next_value, variable);
let loop_end_block = LLVMGetInsertBlock(context.builder);
// LLVMAddIncoming(
// phi,
// vec![next_value].as_mut_slice().as_mut_ptr(),
// vec![loop_block].as_mut_slice().as_mut_ptr(),
// 1 as c_uint,
// );
LLVMBuildBr(context.builder, preloop_block);
......@@ -458,18 +519,20 @@ impl Exp for ForExp {
let mut args_preloop = current_block_args.clone();
let mut form_args_preloop = current_block_form_args.clone();
form_args_preloop.insert(phi_node_name.clone(), phi_node.clone());
args_preloop.push(phi_node.clone_value());
let mut args = vec![];
for (_, arg) in &current_block_form_args {
args.push(arg.clone());
}
args.push(start_exp);
println!("{:?}", current_block.block);
let branch_preloop = create_branch1_instr(vm.vm.next_id(), fun_ver, args, &preloop_block);
current_block.instr.push(branch_preloop);
form_args_preloop.insert(phi_node_name.clone(), phi_node.clone());
args_preloop.push(phi_node.clone_value());
vm.blocks_map.insert(
preloop_block_id,
Mu_Block {
......@@ -1047,7 +1110,18 @@ impl Exp for BinaryExp {
"booltmp\0".as_ptr() as *const c_char,
))
}
'=' => {
let var_name = self.lhs().print(); // format!("{}", self.lhs().print());
let variable = match context.named_values.get(var_name.as_str()) {
Some(vl) => *vl,
None => return Err(String::from("Uknown variable name")),
};
LLVMBuildStore(context.builder, rhs, variable);
Ok(rhs)
}
_ => Err(String::from("Invalid binary operator.")),
}
}
......@@ -1098,7 +1172,15 @@ impl Exp for BinaryExp {
return Ok(var);
}
_ => return Err(String::from("Invalid binary operator.")),
'=' => {
let current_block = mu_vm.blocks_map.get_mut(&mu_vm.curr_block).unwrap();
let var_name = &*lhs.name();
current_block
.form_args
.insert(var_name.clone(), rhs.clone());
return Ok(rhs);
}
_ => unimplemented!(),
};
let binop = function_version.new_inst(Instruction {
......@@ -1149,7 +1231,7 @@ impl Exp for Number {
impl Exp for Var {
fn print(&self) -> String {
format!("Var({})", self.name)
self.name.clone()
}
unsafe fn code_gen(
......@@ -1160,9 +1242,13 @@ impl Exp for Var {
match context.named_values.get(self.name()) {
Some(val) => {
let name = format!("{}\0", self.name.clone());
println!("{}", name);
let var = LLVMBuildLoad( context.builder, *val, name.as_str().as_ptr() as *const c_char);
Ok(var)},
let var = LLVMBuildLoad(
context.builder,
*val,
name.as_str().as_ptr() as *const c_char,
);
Ok(var)
}
None => Err(String::from("Unknown variable name.")),
}
}
......@@ -1176,7 +1262,13 @@ impl Exp for Var {
let r = current_block.form_args.get(self.name.as_str());
match r {
Some(v) => Ok(v.clone()),
Some(v) => {
// let mem_loc = v.clone();
// let (inst, value) = create_mu_load(mu_vm, function_version, mem_loc, self.name.clone());
// let current_block = mu_vm.blocks_map.get_mut(&mu_vm.curr_block).unwrap();
// current_block.instr.push(inst);
Ok(v.clone())
}
None => Err(String::from("Unknown variable name.")),
}
}
......
......@@ -17,13 +17,20 @@ use self::llvm::execution_engine::{
LLVMFreeMachineCodeForFunction, LLVMGenericValueToFloat, LLVMInitializeMCJITCompilerOptions,
LLVMLinkInMCJIT, LLVMMCJITCompilerOptions, LLVMOpaqueExecutionEngine, LLVMRunFunction,
};
use self::llvm::prelude::{LLVMBool, LLVMBuilderRef, LLVMContextRef, LLVMBasicBlockRef};
use self::llvm::prelude::{
LLVMBasicBlockRef, LLVMBool, LLVMBuilderRef, LLVMContextRef, LLVMPassManagerRef,
};
use self::llvm::support::LLVMAddSymbol;
use self::llvm::target::{LLVM_InitializeNativeAsmPrinter, LLVM_InitializeNativeTarget};
use self::llvm::target_machine::{
LLVMCodeGenFileType, LLVMCodeGenOptLevel, LLVMCodeModel, LLVMCreateTargetMachine,
LLVMGetDefaultTargetTriple, LLVMGetFirstTarget, LLVMRelocMode, LLVMTargetMachineEmitToFile,
};
use self::llvm::transforms::scalar::{
LLVMAddBasicAliasAnalysisPass, LLVMAddCFGSimplificationPass, LLVMAddGVNPass,
LLVMAddInstructionCombiningPass, LLVMAddReassociatePass,
};
use self::llvm::transforms::util::LLVMAddPromoteMemoryToRegisterPass;
use self::llvm::LLVMRealPredicate::LLVMRealOLT;
use self::llvm::{LLVMModule, LLVMType, LLVMValue};
use crate::lexer::Token::CHAR;
......@@ -37,10 +44,11 @@ pub struct Context {
pub named_values: HashMap<String, LLVMValueRef>,
pub ty: *mut LLVMType,
pub curr_function: i32,
pub pass_manager: LLVMPassManagerRef,
}
impl Context {
pub unsafe fn new() -> Context {
pub unsafe fn new(pass_manager: LLVMPassManagerRef) -> Context {
let context = llvm::core::LLVMContextCreate();
let builder = llvm::core::LLVMCreateBuilderInContext(context);
let named_values = HashMap::new();
......@@ -52,6 +60,7 @@ impl Context {
named_values,
ty,
curr_function: 0,
pass_manager,
}
}
......@@ -161,13 +170,21 @@ pub unsafe fn init() {
pub unsafe fn code_gen(filename: String, nodes: ASTNodes) -> Vec<Result<f64, String>> {
init();
let mut context = Context::new();
let module = llvm::core::LLVMModuleCreateWithName(filename.as_str().as_ptr() as *const _);
let function_pass_manager = LLVMCreateFunctionPassManagerForModule(module);
LLVMAddBasicAliasAnalysisPass(function_pass_manager);
LLVMAddInstructionCombiningPass(function_pass_manager);
LLVMAddReassociatePass(function_pass_manager);
LLVMAddGVNPass(function_pass_manager);
LLVMAddCFGSimplificationPass(function_pass_manager);
LLVMInitializeFunctionPassManager(function_pass_manager);
LLVMAddPromoteMemoryToRegisterPass(function_pass_manager);
let mut context = Context::new(function_pass_manager);
let mut module_number = 0;
let mut returning_values = vec![];
let module = llvm::core::LLVMModuleCreateWithName(filename.as_str().as_ptr() as *const _);
for prototype in nodes.prototypes {
let out_file = CString::new(format!("out_{}.ll", module_number)).unwrap();
prototype.code_gen(&module, &mut context);
......@@ -187,7 +204,8 @@ pub unsafe fn code_gen(filename: String, nodes: ASTNodes) -> Vec<Result<f64, Str
returning_values.push(run_function(result, module, &mut context));
}
let module = llvm::core::LLVMModuleCreateWithName(filename.as_str().as_ptr() as *const _);
let context = Context::new();
let function_pass_manager = LLVMCreateFunctionPassManagerForModule(module);
let context = Context::new(function_pass_manager);
}
returning_values
......@@ -272,11 +290,16 @@ pub fn get_function_by_name(function: *mut LLVMModule, name: &str) -> Option<*mu
}
}
pub unsafe fn create_block_alloca(context : &mut Context, block : LLVMBasicBlockRef, var_name : &str) -> LLVMValueRef {
pub unsafe fn create_block_alloca(
context: &mut Context,
block: LLVMBasicBlockRef,
var_name: &str,
) -> LLVMValueRef {
let builder = LLVMCreateBuilder();
let fi = LLVMGetFirstInstruction(block);
LLVMPositionBuilder(builder, block, fi);
LLVMBuildAlloca(builder, context.ty, var_name.as_ptr() as *const c_char)
let var = format!("{}\0", var_name);
LLVMBuildAlloca(builder, context.ty, var.as_str().as_ptr() as *const c_char)
}
impl Code_gen for Function {
......@@ -303,7 +326,7 @@ impl Code_gen for Function {
// set function parameters
for (param, arg) in get_params(function).iter().zip(self.proto().args()) {
let arg_alloca = create_block_alloca(context, basic_block, arg.clone().as_str());
LLVMBuildStore(context.builder, *param, arg_alloca);
LLVMBuildStore(context.builder, *param, arg_alloca);
context.named_values.insert(arg.clone(), arg_alloca);
}
......@@ -318,6 +341,7 @@ impl Code_gen for Function {
LLVMBuildRet(context.builder, body);
LLVMVerifyFunction(function, LLVMAbortProcessAction);
LLVMRunFunctionPassManager(context.pass_manager, function);
Ok(function)
}
......
......@@ -24,14 +24,6 @@ pub fn read_file() -> (String, Vec<Token>) {
let mut filename = String::new();
// let result = match io::stdin().read_line(&mut filename) {
// Ok(_) => (),
// Err(e) => {
// println!("{}", e);
// continue;
// }
// };
let exit_code = String::from(".quit");
if filename.trim().eq(&exit_code) {
......
......@@ -12,8 +12,10 @@ pub mod parser;
pub mod mu_generator;
fn main() {
const USE_LLVM: bool = true;
const USE_AOT_MU_LLVM: bool = true;
const USE_LLVM: bool = false;
const USE_AOT_MU_LLVM: bool = false;
const USE_ALLOCA: bool = false;
const USE_NEW: bool = false;
// process chars into tokens
let (filename, tokens) = lexer::read_file();
......@@ -31,7 +33,8 @@ fn main() {
}
} else {
unsafe {
values = mu_generator::code_gen(filename, nodes, USE_AOT_MU_LLVM, true);
values =
mu_generator::code_gen(filename, nodes, USE_AOT_MU_LLVM, true, USE_ALLOCA, USE_NEW);
}
}
......
......@@ -42,10 +42,12 @@ pub struct Mu_VM {
pub whitelist: Vec<MuID>,
pub last_runnable_function: Option<MuEntityHeader>,
pub name_generator: HashMap<String, i32>,
pub use_alloca: bool,
pub use_new: bool,
}
impl Mu_VM {
pub fn new(use_llvm_aot: bool, debug: bool) -> Mu_VM {
pub fn new(use_llvm_aot: bool, debug: bool, use_alloca: bool, use_new: bool) -> Mu_VM {
let debug_opt = "--log-level=debug --emit-debug-info ";
let generate_llvm_opt = "--generate-llvm";
let mut opts = String::from("init_mu");
......@@ -91,6 +93,8 @@ impl Mu_VM {
whitelist,
last_runnable_function: None,
name_generator: HashMap::new(),
use_alloca,
use_new,
}
}
......@@ -122,8 +126,10 @@ pub unsafe fn code_gen(
nodes: ASTNodes,
use_llvm_aot: bool,
debug: bool,
use_alloca: bool,
use_new: bool,
) -> Vec<Result<f64, String>> {
let mut vm = Mu_VM::new(use_llvm_aot, debug);
let mut vm = Mu_VM::new(use_llvm_aot, debug, use_alloca, use_new);
let mut results = vec![];
for prototype in nodes.prototypes {
......@@ -259,6 +265,7 @@ impl Mu_code_gen for Function {
let mut args = vec![];
let mut form_args = LinkedHashMap::new();
let mut alloca_instr = vec![];
for arg in self.proto().args() {
let form_arg = function_version.new_ssa(
......@@ -266,6 +273,20 @@ impl Mu_code_gen for Function {
mu_vm.ty.clone(),
);
mu_vm.vm.set_name(form_arg.as_entity());
if mu_vm.use_alloca {
let (loc_var, instr) =
create_mu_alloca(mu_vm, &mut function_version, mu_vm.ty.clone(), arg.clone());
alloca_instr.push(instr);
alloca_instr.push(create_mu_store(
mu_vm,
&mut function_version,
form_arg.clone(),
loc_var.clone(),
mu_vm.ty.clone(),
));
}
form_args.insert(arg.clone(), form_arg.clone());
args.push(form_arg.clone_value());
}
......@@ -273,13 +294,15 @@ impl Mu_code_gen for Function {
let mut blk_entry = Block::new(MuEntityHeader::named(mu_vm.vm.next_id(), Mu("blk_entry")));
&mu_vm.vm.set_name(blk_entry.as_entity());
println!("{:?}", args);
let blk_entry_id = blk_entry.hdr.id();
mu_vm.curr_block = blk_entry_id;
mu_vm.blocks_map.insert(
blk_entry.hdr.id(),
Mu_Block {
block: blk_entry,
instr: vec![],
instr: alloca_instr,
args,
form_args,
},
......@@ -327,6 +350,87 @@ impl Mu_code_gen for Function {
}
}
pub fn create_mu_load(
mu_vm: &mut Mu_VM,
func_version: &mut MuFunctionVersion,
mem_loc: P<TreeNode>,
name: String,
) -> (P<TreeNode>, P<TreeNode>) {
let var_loaded_name = format!("{}_l", name);
let var_loaded = func_version.new_ssa(
MuEntityHeader::named(mu_vm.vm.next_id(), Arc::new(var_loaded_name.clone())),
mu_vm.ty.clone(),
);
mu_vm.vm.set_name(var_loaded.as_entity());
println!("at load : {:?}", mem_loc);
let new_load_instr = func_version.new_inst(Instruction {
hdr: MuEntityHeader::unnamed(mu_vm.vm.next_id()),
value: Some(vec![var_loaded.clone_value()]),
ops: vec![mem_loc],
v: Instruction_::Load {
is_ptr: false,
order: MemoryOrder::SeqCst,
mem_loc: 0,
},
});
(var_loaded, new_load_instr)
}
pub fn create_mu_store(
mu_vm: &mut Mu_VM,
func_version: &mut MuFunctionVersion,
value: P<TreeNode>,
mem_loc: P<TreeNode>,
alloca_type: P<MuType>,
) -> P<TreeNode> {
let new_store_instr = func_version.new_inst(Instruction {
hdr: MuEntityHeader::unnamed(mu_vm.vm.next_id()),
value: None,
ops: vec![value, mem_loc],
v: Instruction_::Store {
is_ptr: false,
order: MemoryOrder::SeqCst,
mem_loc: 1,
value: 0,
},
});
new_store_instr
}
pub fn create_mu_alloca(
mu_vm: &mut Mu_VM,
func_version: &mut MuFunctionVersion,
alloca_type: P<MuType>,
name: String,
) -> (P<TreeNode>, P<TreeNode>) {
let mem_loc_type = mu_vm.vm.declare_type(
MuEntityHeader::unnamed(mu_vm.vm.next_id()),
MuType_::iref(alloca_type.clone()),
);
mu_vm.vm.set_name(mem_loc_type.as_entity());
let mem_loc_name = mu_vm.generate_name(format!("loc_{}", name));
let mem_loc = func_version.new_ssa(
MuEntityHeader::named(mu_vm.vm.next_id(), Arc::new(mem_loc_name.clone())),
mem_loc_type,
);
mu_vm.vm.set_name(mem_loc.as_entity());