Try add some display for LLIR
This commit is contained in:
parent
f55040ad00
commit
1ba1ae3213
@ -67,7 +67,7 @@ pub struct InstructionHolder {
|
||||
|
||||
#[derive(Clone)]
|
||||
pub(crate) struct Builder {
|
||||
modules: Rc<RefCell<Vec<ModuleHolder>>>,
|
||||
pub(crate) modules: Rc<RefCell<Vec<ModuleHolder>>>,
|
||||
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
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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<RefCell<Vec<DebugMetadataHolder>>> {
|
||||
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<DebugSubprogramData> {
|
||||
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<RefCell<Vec<DebugMetadataHolder>>> {
|
||||
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()
|
||||
|
@ -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<DebugInformation>,
|
||||
) -> 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::<Vec<_>>()
|
||||
.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<DebugInformation>,
|
||||
) -> 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<DebugInformation>,
|
||||
) -> 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)
|
||||
|
@ -16,6 +16,7 @@ pub mod builder;
|
||||
pub mod compile;
|
||||
pub mod debug_information;
|
||||
mod fmt;
|
||||
mod pad_adapter;
|
||||
mod util;
|
||||
|
||||
#[derive(Debug)]
|
||||
|
69
reid-llvm-lib/src/pad_adapter.rs
Normal file
69
reid-llvm-lib/src/pad_adapter.rs
Normal file
@ -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)
|
||||
}
|
||||
}
|
@ -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> {
|
||||
|
@ -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())
|
||||
|
Loading…
Reference in New Issue
Block a user