diff --git a/reid-llvm-lib/src/builder.rs b/reid-llvm-lib/src/builder.rs index 14c0cbd..5b39f43 100644 --- a/reid-llvm-lib/src/builder.rs +++ b/reid-llvm-lib/src/builder.rs @@ -67,7 +67,7 @@ pub struct InstructionHolder { #[derive(Clone)] pub(crate) struct Builder { - modules: Rc>>, + pub(crate) modules: Rc>>, pub(crate) producer: String, } @@ -368,7 +368,6 @@ impl Builder { } Instr::FunctionCall(fun, params) => { let param_types = self.function_data(&fun).params; - dbg!(¶m_types, ¶ms); if param_types.len() != params.len() { return Err(()); // TODO error: invalid amount of params } diff --git a/reid-llvm-lib/src/compile.rs b/reid-llvm-lib/src/compile.rs index 3ca93c5..8352e10 100644 --- a/reid-llvm-lib/src/compile.rs +++ b/reid-llvm-lib/src/compile.rs @@ -339,7 +339,7 @@ impl ModuleHolder { debug.locations.insert(location.value, location_ref); } - for meta in debug.debug.get_metadata().borrow().iter() { + for meta in debug.debug.get_metadatas().borrow().iter() { let meta_ref = meta.compile(&debug); debug.metadata.insert(meta.value.clone(), meta_ref); } @@ -606,7 +606,7 @@ impl FunctionHolder { let metadata = if let Some(debug) = debug { if let Some(value) = &self.data.debug { - let subprogram = debug.debug.get_subprogram_data(&value); + let subprogram = debug.debug.get_subprogram_data_unchecked(&value); let mangled_length_ptr = &mut 0; let mangled_name = LLVMGetValueName2(function_ref, mangled_length_ptr); diff --git a/reid-llvm-lib/src/debug_information.rs b/reid-llvm-lib/src/debug_information.rs index 575fc35..d364332 100644 --- a/reid-llvm-lib/src/debug_information.rs +++ b/reid-llvm-lib/src/debug_information.rs @@ -1,4 +1,4 @@ -use std::{cell::RefCell, rc::Rc}; +use std::{cell::RefCell, collections::hash_map::Values, rc::Rc}; use crate::builder::InstructionValue; @@ -161,7 +161,33 @@ impl DebugInformation { value } - pub fn get_metadata(&self) -> Rc>> { + pub fn get_metadata(&self, value: DebugMetadataValue) -> DebugMetadata { + unsafe { self.metadata.borrow().get_unchecked(value.0).data.clone() } + } + + pub fn get_subprogram_data(&self, value: DebugProgramValue) -> Option { + if value.0 == 0 { + None + } else { + Some(self.get_subprogram_data_unchecked(&value)) + } + } + + pub fn get_type_data(&self, value: DebugTypeValue) -> DebugTypeData { + unsafe { self.types.borrow().get_unchecked(value.0).data.clone() } + } + + pub fn get_location(&self, value: DebugLocationValue) -> DebugLocation { + unsafe { + self.locations + .borrow() + .get_unchecked(value.1) + .location + .clone() + } + } + + pub fn get_metadatas(&self) -> Rc>> { self.metadata.clone() } @@ -181,7 +207,7 @@ impl DebugInformation { self.locations.clone() } - pub fn get_subprogram_data(&self, value: &DebugProgramValue) -> DebugSubprogramData { + pub fn get_subprogram_data_unchecked(&self, value: &DebugProgramValue) -> DebugSubprogramData { unsafe { self.programs .borrow() diff --git a/reid-llvm-lib/src/fmt.rs b/reid-llvm-lib/src/fmt.rs index 24b9b94..0336a38 100644 --- a/reid-llvm-lib/src/fmt.rs +++ b/reid-llvm-lib/src/fmt.rs @@ -1,20 +1,187 @@ //! Debug implementations for relevant types use std::{ - fmt::{Debug, Write}, + fmt::{Debug, Display, Write}, marker::PhantomData, }; use crate::{ - CmpPredicate, Instr, InstructionData, TerminatorKind, + CmpPredicate, Context, Instr, InstructionData, TerminatorKind, builder::*, debug_information::{ - DebugArrayType, DebugBasicType, DebugFieldType, DebugLocation, DebugLocationValue, - DebugMetadataValue, DebugPointerType, DebugProgramValue, DebugScopeValue, DebugStructType, + DebugArrayType, DebugBasicType, DebugFieldType, DebugInformation, DebugLocalVariable, + DebugLocation, DebugLocationValue, DebugMetadata, DebugMetadataValue, DebugParamVariable, + DebugPointerType, DebugProgramValue, DebugRecordKind, DebugScopeValue, DebugStructType, DebugSubprogramType, DebugTypeData, DebugTypeHolder, DebugTypeValue, }, + pad_adapter::PadAdapter, }; +impl Display for Context { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + Display::fmt(&self.builder, f) + } +} + +impl Display for Builder { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + writeln!(f, "Producer: {}", self.producer)?; + for module in self.modules.borrow().iter() { + if module.data.is_main { + write!(f, "main ")?; + } + writeln!(f, "{} ({:?}) {{", module.data.name, module.value)?; + for function in &module.functions { + let mut state = Default::default(); + let mut inner = PadAdapter::wrap(f, &mut state); + function.builder_fmt(&mut inner, self, &module.debug_information)?; + } + writeln!(f, "}}")?; + } + Ok(()) + } +} + +impl FunctionHolder { + fn builder_fmt( + &self, + f: &mut impl std::fmt::Write, + builder: &Builder, + debug: &Option, + ) -> std::fmt::Result { + if self.data.flags.is_imported { + write!(f, "imported ")?; + } + if self.data.flags.is_extern { + write!(f, "extern ")?; + } + if self.data.flags.is_pub { + write!(f, "pub ")?; + } + if self.data.flags.is_main { + write!(f, "main ")?; + } + let params = self + .data + .params + .iter() + .map(|p| format!("{:?}", p)) + .collect::>() + .join(", "); + write!( + f, + "fn {}({}) -> {:?} ", + self.data.name, params, self.data.ret + )?; + + writeln!(f, "{{")?; + let mut state = Default::default(); + let mut inner = PadAdapter::wrap(f, &mut state); + writeln!(inner, "(Value = {:?}) ", self.value)?; + if let Some(debug) = self.data.debug { + writeln!(inner, "(Debug = {:?})", debug)?; + } + + for block in &self.blocks { + let mut state = Default::default(); + let mut inner = PadAdapter::wrap(&mut inner, &mut state); + block.builder_fmt(&mut inner, builder, debug)?; + } + + writeln!(f, "}}")?; + Ok(()) + } +} + +impl BlockHolder { + fn builder_fmt( + &self, + f: &mut impl std::fmt::Write, + builder: &Builder, + debug: &Option, + ) -> std::fmt::Result { + if self.data.deleted { + write!(f, "deleted ")?; + } + writeln!(f, "{} ({:?}):", self.data.name, self.value)?; + + for instr in &self.instructions { + let mut state = Default::default(); + let mut inner = PadAdapter::wrap(f, &mut state); + instr.builder_fmt(&mut inner, builder, debug)?; + } + + Ok(()) + } +} + +impl InstructionHolder { + fn builder_fmt( + &self, + f: &mut impl std::fmt::Write, + builder: &Builder, + debug: &Option, + ) -> std::fmt::Result { + if let Some(record) = &self.record { + let kind = match record.kind { + DebugRecordKind::Declare(instruction_value) => { + format!("= {:?} (Assign)", instruction_value) + } + DebugRecordKind::Value(instruction_value) => { + format!("= {:?} (Value)", instruction_value) + } + }; + + if let Some(debug) = debug { + writeln!(f, " (Debug {} {})", record.variable.hr(debug), kind)?; + } + } + writeln!( + f, + "{:?} ({}) = {:?} ", + self.value, self.name, self.data.kind + )?; + if let Some(debug) = debug { + if let Some(location) = self.data.location { + writeln!(f, " ^ (At {}) ", debug.get_location(location))?; + } + if let Some(meta) = self.data.meta { + writeln!(f, " ^ (Meta {}) ", meta.hr(debug))?; + } + } + writeln!(f)?; + + Ok(()) + } +} + +impl DebugMetadataValue { + fn hr(&self, debug: &DebugInformation) -> String { + match debug.get_metadata(*self) { + DebugMetadata::ParamVar(DebugParamVariable { + name, + arg_idx, + location, + ty, + .. + }) => format!( + "param {} (idx {}) (type {:?}) at {}", + name, arg_idx, ty, location + ), + DebugMetadata::LocalVar(DebugLocalVariable { + name, location, ty, .. + }) => format!("var {} (type {:?}) at {}", name, ty, location), + DebugMetadata::VarAssignment => todo!(), + } + } +} + +impl Display for DebugLocation { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "line {}, col {}", self.line, self.column) + } +} + impl Debug for Builder { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_list().entries(self.get_modules().borrow().iter()); @@ -29,7 +196,7 @@ pub struct PrintableModule<'ctx> { impl<'ctx> Debug for PrintableModule<'ctx> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - self.module.fmt(f) + Debug::fmt(&self.module, f) } } @@ -108,12 +275,22 @@ impl Debug for InstructionValue { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!( f, - "I[{:0>2}-{:0>2}-{:0>2}-{:0>2}]", - &self.0.0.0.0, &self.0.0.1, &self.0.1, self.1 + "%{}.{}.{}.{}", + self.0.0.0.0, self.0.0.1, self.0.1, self.1 ) } } +// impl Debug for InstructionValue { +// fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { +// write!( +// f, +// "I[{:0>2}-{:0>2}-{:0>2}-{:0>2}]", +// &self.0.0.0.0, &self.0.0.1, &self.0.1, self.1 +// ) +// } +// } + impl Debug for TypeValue { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "Ty[{:0>2}-{:0>2}]", &self.0.0, self.1) diff --git a/reid-llvm-lib/src/lib.rs b/reid-llvm-lib/src/lib.rs index 16827c9..91244d5 100644 --- a/reid-llvm-lib/src/lib.rs +++ b/reid-llvm-lib/src/lib.rs @@ -16,6 +16,7 @@ pub mod builder; pub mod compile; pub mod debug_information; mod fmt; +mod pad_adapter; mod util; #[derive(Debug)] diff --git a/reid-llvm-lib/src/pad_adapter.rs b/reid-llvm-lib/src/pad_adapter.rs new file mode 100644 index 0000000..3014fa3 --- /dev/null +++ b/reid-llvm-lib/src/pad_adapter.rs @@ -0,0 +1,69 @@ +//! Copied from +//! https://github.com/rust-lang/rust/blob/6b3ae3f6e45a33c2d95fa0362c9b2593e567fd34/library/core/src/fmt/builders.rs#L102 + +// Copyright (c) The Rust Project Contributors +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +use std::fmt; + +pub struct PadAdapter<'buf, 'state> { + buf: &'buf mut (dyn fmt::Write + 'buf), + state: &'state mut PadAdapterState, +} + +pub struct PadAdapterState { + on_newline: bool, +} + +impl Default for PadAdapterState { + fn default() -> Self { + PadAdapterState { on_newline: true } + } +} + +impl<'buf, 'state> PadAdapter<'buf, 'state> { + pub fn wrap<'slot, 'fmt: 'buf + 'slot>( + fmt: &'buf mut (dyn fmt::Write + 'buf), + state: &'state mut PadAdapterState, + ) -> Self { + PadAdapter { buf: fmt, state } + } +} + +impl fmt::Write for PadAdapter<'_, '_> { + fn write_str(&mut self, s: &str) -> fmt::Result { + for s in s.split_inclusive('\n') { + if self.state.on_newline { + self.buf.write_str(" ")?; + } + self.state.on_newline = s.ends_with('\n'); + self.buf.write_str(s)?; + } + Ok(()) + } + + fn write_char(&mut self, c: char) -> fmt::Result { + if self.state.on_newline { + self.buf.write_str(" ")?; + } + self.state.on_newline = c == '\n'; + self.buf.write_char(c) + } +} diff --git a/reid/src/codegen.rs b/reid/src/codegen.rs index 1abfbdc..15a1edd 100644 --- a/reid/src/codegen.rs +++ b/reid/src/codegen.rs @@ -27,7 +27,7 @@ use crate::{ /// LLIR that can then be finally compiled into LLVM IR. #[derive(Debug)] pub struct CodegenContext<'ctx> { - context: &'ctx Context, + pub(crate) context: &'ctx Context, } impl<'ctx> CodegenContext<'ctx> { diff --git a/reid/src/lib.rs b/reid/src/lib.rs index 179a6f7..ff482d4 100644 --- a/reid/src/lib.rs +++ b/reid/src/lib.rs @@ -123,6 +123,8 @@ pub fn perform_all_passes<'map>( let state = context.pass(&mut LinkerPass { module_map })?; + #[cfg(debug_assertions)] + println!("{:-^100}", "LINKER OUTPUT"); #[cfg(debug_assertions)] println!("{}", &context); #[cfg(debug_assertions)] @@ -139,6 +141,8 @@ pub fn perform_all_passes<'map>( let state = context.pass(&mut TypeInference { refs: &refs })?; + #[cfg(debug_assertions)] + println!("{:-^100}", "TYPE INFERRER OUTPUT"); #[cfg(debug_assertions)] dbg!(&refs); #[cfg(debug_assertions)] @@ -159,6 +163,8 @@ pub fn perform_all_passes<'map>( let state = context.pass(&mut TypeCheck { refs: &refs })?; + #[cfg(debug_assertions)] + println!("{:-^100}", "TYPECHECKER OUTPUT"); #[cfg(debug_assertions)] println!("{}", &context); #[cfg(debug_assertions)] @@ -197,7 +203,7 @@ pub fn compile_and_pass<'map>( perform_all_passes(&mut mir_context, module_map)?; #[cfg(debug_assertions)] - dbg!(&mir_context); + println!("{:-^100}", "FINAL OUTPUT"); #[cfg(debug_assertions)] println!("{}", &mir_context); @@ -205,7 +211,7 @@ pub fn compile_and_pass<'map>( let codegen_modules = mir_context.codegen(&mut context, &module_map); #[cfg(debug_assertions)] - dbg!(&codegen_modules); + println!("{}", &codegen_modules.context); let compiled = codegen_modules.compile(); Ok(compiled.output())