From bdd6f75cf6ace3844f9fc218e30e6b09dc1b883a Mon Sep 17 00:00:00 2001 From: greg Date: Mon, 16 Jan 2017 02:38:58 -0800 Subject: [PATCH] Show/hide LLVM IR in REPL --- src/compilation.rs | 18 +++++++++----- src/llvm_wrap.rs | 8 +++++- src/main.rs | 62 ++++++++++++++++++++++++++++------------------ 3 files changed, 57 insertions(+), 31 deletions(-) diff --git a/src/compilation.rs b/src/compilation.rs index 37cedaf..b8ac7b5 100644 --- a/src/compilation.rs +++ b/src/compilation.rs @@ -20,7 +20,7 @@ pub fn compilation_sequence(ast: AST, sourcefile: &str) { _ => panic!("Bad filename {}", sourcefile), }; - compile_ast(ast, ll_filename); + compile_ast(ast, ll_filename, false); let llc_output = Command::new("llc") .arg("-filetype=obj") .arg(ll_filename) @@ -57,7 +57,7 @@ struct CompilationData { main_function: LLVMValueRef, } -fn compile_ast(ast: AST, filename: &str) { +pub fn compile_ast(ast: AST, filename: &str, return_string: bool) -> Option { println!("Compiling!"); let names: VariableMap = HashMap::new(); @@ -84,13 +84,21 @@ fn compile_ast(ast: AST, filename: &str) { LLVMWrap::BuildRet(builder, value); - println!("Printing {} to file", filename); - LLVMWrap::PrintModuleToFile(module, filename); + println!("Compilation process finished for {}", filename); + let ret = if return_string { + let s = LLVMWrap::PrintModuleToString(module); + Some(s) + } else { + LLVMWrap::PrintModuleToFile(module, filename); + None + }; // Clean up. Values created in the context mostly get cleaned up there. LLVMWrap::DisposeBuilder(builder); LLVMWrap::DisposeModule(module); LLVMWrap::ContextDispose(context); + + ret } trait CodeGen { @@ -172,10 +180,8 @@ impl CodeGen for Prototype { function_type); let function_params = LLVMWrap::GetParams(function); - println!("Params: {:?}", function_params); for (index, param) in function_params.iter().enumerate() { let name = self.parameters.get(index).expect(&format!("Failed this check at index {}", index)); - println!("Gonna set value name for : {}, value is {:?}", name, param); let new = *param; LLVMWrap::SetValueName(new, name); diff --git a/src/llvm_wrap.rs b/src/llvm_wrap.rs index 010698f..b145695 100644 --- a/src/llvm_wrap.rs +++ b/src/llvm_wrap.rs @@ -178,7 +178,6 @@ pub fn AddIncoming(phi: LLVMValueRef, incoming_values: *mut LLVMValueRef, incomi pub fn SetValueName(value: LLVMValueRef, name: &str) { let name = CString::new(name).unwrap(); - println!("Value: {:?}", value); unsafe { core::LLVMSetValueName(value, name.as_ptr()) } @@ -254,6 +253,13 @@ pub fn CountBasicBlocks(function: LLVMValueRef) -> usize { unsafe { core::LLVMCountBasicBlocks(function) as usize } } +pub fn PrintModuleToString(module: LLVMModuleRef) -> String { + unsafe { + let str_ptr: *const c_char = core::LLVMPrintModuleToString(module); + CStr::from_ptr(str_ptr).to_string_lossy().into_owned() + } +} + pub fn PrintModuleToFile(module: LLVMModuleRef, filename: &str) -> LLVMBool { let out_file = CString::new(filename).unwrap(); unsafe { core::LLVMPrintModuleToFile(module, out_file.as_ptr(), ptr::null_mut()) } diff --git a/src/main.rs b/src/main.rs index 9576747..e498324 100644 --- a/src/main.rs +++ b/src/main.rs @@ -16,7 +16,7 @@ mod parser; use eval::Evaluator; mod eval; -use compilation::compilation_sequence; +use compilation::{compilation_sequence, compile_ast}; mod compilation; mod llvm_wrap; @@ -89,6 +89,7 @@ type LineReader = linefeed::Reader; struct Repl<'a> { show_tokens: bool, show_parse: bool, + show_llvm_ir: bool, evaluator: Evaluator<'a>, interpreter_directive_sigil: char, reader: LineReader, @@ -101,6 +102,7 @@ impl<'a> Repl<'a> { Repl { show_tokens: false, show_parse: false, + show_llvm_ir: false, evaluator: Evaluator::new_with_opts(None, trace_evaluation), interpreter_directive_sigil: '.', reader: reader, @@ -132,30 +134,41 @@ impl<'a> Repl<'a> { } fn input_handler(&mut self, input: &str) -> String { - let mut result = String::new(); - let intermediate: Result = - tokenize(input) - .map_err(|e| format!("Tokenization error: {}", e.msg)) - .and_then( - |tokens| { - if self.show_tokens { - result.push_str(&format!("Tokens: {:?}\n", tokens)); - } - parse(&tokens, &[]).map_err(|e| format!("Parse error: {}", e.msg)) - }) - .and_then( - |ast| { - if self.show_parse { - result.push_str(&format!("AST: {:?}\n", ast)); - } - // for now only handle last output - let mut full_output: Vec = self.evaluator.run(ast); - Ok(full_output.pop().unwrap_or("".to_string())) - }); - match intermediate { - Ok(s) | Err(s) => result.push_str(&s), + let mut output = String::new(); + + let tokens = match tokenize(input) { + Ok(tokens) => tokens, + Err(err) => { + output.push_str(&format!("Tokenization error: {}\n", err.msg)); + return output; + } }; - result + + if self.show_tokens { + output.push_str(&format!("Tokens: {:?}\n", tokens)); + } + + let ast = match parse(&tokens, &[]) { + Ok(ast) => ast, + Err(err) => { + output.push_str(&format!("Parse error: {:?}\n", err.msg)); + return output; + } + }; + + if self.show_parse { + output.push_str(&format!("AST: {:?}\n", ast)); + } + + if self.show_llvm_ir { + let s = compile_ast(ast, "«repl llvm»", true).unwrap(); + output.push_str(&s); + } else { + // for now only handle last output + let mut full_output: Vec = self.evaluator.run(ast); + output.push_str(&full_output.pop().unwrap_or("".to_string())); + } + output } fn handle_interpreter_directive(&mut self, input: &str) -> bool { @@ -197,6 +210,7 @@ impl<'a> Repl<'a> { "tokens" => self.show_tokens = show, "parse" => self.show_parse = show, "eval" => self.evaluator.trace_evaluation = show, + "llvm" => self.show_llvm_ir = show, e => { println!("Bad `show`/`hide` argument: {}", e); return true;