Show/hide LLVM IR in REPL

This commit is contained in:
greg 2017-01-16 02:38:58 -08:00
parent 2681dbc4f2
commit bdd6f75cf6
3 changed files with 57 additions and 31 deletions

View File

@ -20,7 +20,7 @@ pub fn compilation_sequence(ast: AST, sourcefile: &str) {
_ => panic!("Bad filename {}", sourcefile), _ => panic!("Bad filename {}", sourcefile),
}; };
compile_ast(ast, ll_filename); compile_ast(ast, ll_filename, false);
let llc_output = Command::new("llc") let llc_output = Command::new("llc")
.arg("-filetype=obj") .arg("-filetype=obj")
.arg(ll_filename) .arg(ll_filename)
@ -57,7 +57,7 @@ struct CompilationData {
main_function: LLVMValueRef, main_function: LLVMValueRef,
} }
fn compile_ast(ast: AST, filename: &str) { pub fn compile_ast(ast: AST, filename: &str, return_string: bool) -> Option<String> {
println!("Compiling!"); println!("Compiling!");
let names: VariableMap = HashMap::new(); let names: VariableMap = HashMap::new();
@ -84,13 +84,21 @@ fn compile_ast(ast: AST, filename: &str) {
LLVMWrap::BuildRet(builder, value); LLVMWrap::BuildRet(builder, value);
println!("Printing {} to file", filename); println!("Compilation process finished for {}", filename);
LLVMWrap::PrintModuleToFile(module, 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. // Clean up. Values created in the context mostly get cleaned up there.
LLVMWrap::DisposeBuilder(builder); LLVMWrap::DisposeBuilder(builder);
LLVMWrap::DisposeModule(module); LLVMWrap::DisposeModule(module);
LLVMWrap::ContextDispose(context); LLVMWrap::ContextDispose(context);
ret
} }
trait CodeGen { trait CodeGen {
@ -172,10 +180,8 @@ impl CodeGen for Prototype {
function_type); function_type);
let function_params = LLVMWrap::GetParams(function); let function_params = LLVMWrap::GetParams(function);
println!("Params: {:?}", function_params);
for (index, param) in function_params.iter().enumerate() { for (index, param) in function_params.iter().enumerate() {
let name = self.parameters.get(index).expect(&format!("Failed this check at index {}", index)); 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; let new = *param;
LLVMWrap::SetValueName(new, name); LLVMWrap::SetValueName(new, name);

View File

@ -178,7 +178,6 @@ pub fn AddIncoming(phi: LLVMValueRef, incoming_values: *mut LLVMValueRef, incomi
pub fn SetValueName(value: LLVMValueRef, name: &str) { pub fn SetValueName(value: LLVMValueRef, name: &str) {
let name = CString::new(name).unwrap(); let name = CString::new(name).unwrap();
println!("Value: {:?}", value);
unsafe { unsafe {
core::LLVMSetValueName(value, name.as_ptr()) core::LLVMSetValueName(value, name.as_ptr())
} }
@ -254,6 +253,13 @@ pub fn CountBasicBlocks(function: LLVMValueRef) -> usize {
unsafe { core::LLVMCountBasicBlocks(function) as 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 { pub fn PrintModuleToFile(module: LLVMModuleRef, filename: &str) -> LLVMBool {
let out_file = CString::new(filename).unwrap(); let out_file = CString::new(filename).unwrap();
unsafe { core::LLVMPrintModuleToFile(module, out_file.as_ptr(), ptr::null_mut()) } unsafe { core::LLVMPrintModuleToFile(module, out_file.as_ptr(), ptr::null_mut()) }

View File

@ -16,7 +16,7 @@ mod parser;
use eval::Evaluator; use eval::Evaluator;
mod eval; mod eval;
use compilation::compilation_sequence; use compilation::{compilation_sequence, compile_ast};
mod compilation; mod compilation;
mod llvm_wrap; mod llvm_wrap;
@ -89,6 +89,7 @@ type LineReader = linefeed::Reader<linefeed::terminal::DefaultTerminal>;
struct Repl<'a> { struct Repl<'a> {
show_tokens: bool, show_tokens: bool,
show_parse: bool, show_parse: bool,
show_llvm_ir: bool,
evaluator: Evaluator<'a>, evaluator: Evaluator<'a>,
interpreter_directive_sigil: char, interpreter_directive_sigil: char,
reader: LineReader, reader: LineReader,
@ -101,6 +102,7 @@ impl<'a> Repl<'a> {
Repl { Repl {
show_tokens: false, show_tokens: false,
show_parse: false, show_parse: false,
show_llvm_ir: false,
evaluator: Evaluator::new_with_opts(None, trace_evaluation), evaluator: Evaluator::new_with_opts(None, trace_evaluation),
interpreter_directive_sigil: '.', interpreter_directive_sigil: '.',
reader: reader, reader: reader,
@ -132,30 +134,41 @@ impl<'a> Repl<'a> {
} }
fn input_handler(&mut self, input: &str) -> String { fn input_handler(&mut self, input: &str) -> String {
let mut result = String::new(); let mut output = String::new();
let intermediate: Result<String, String> =
tokenize(input) let tokens = match tokenize(input) {
.map_err(|e| format!("Tokenization error: {}", e.msg)) Ok(tokens) => tokens,
.and_then( Err(err) => {
|tokens| { output.push_str(&format!("Tokenization error: {}\n", err.msg));
if self.show_tokens { return output;
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<String> = self.evaluator.run(ast);
Ok(full_output.pop().unwrap_or("".to_string()))
});
match intermediate {
Ok(s) | Err(s) => result.push_str(&s),
}; };
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<String> = self.evaluator.run(ast);
output.push_str(&full_output.pop().unwrap_or("".to_string()));
}
output
} }
fn handle_interpreter_directive(&mut self, input: &str) -> bool { fn handle_interpreter_directive(&mut self, input: &str) -> bool {
@ -197,6 +210,7 @@ impl<'a> Repl<'a> {
"tokens" => self.show_tokens = show, "tokens" => self.show_tokens = show,
"parse" => self.show_parse = show, "parse" => self.show_parse = show,
"eval" => self.evaluator.trace_evaluation = show, "eval" => self.evaluator.trace_evaluation = show,
"llvm" => self.show_llvm_ir = show,
e => { e => {
println!("Bad `show`/`hide` argument: {}", e); println!("Bad `show`/`hide` argument: {}", e);
return true; return true;