Skip to content

Commit

Permalink
test(cfc): Add codegen tests for CFC debugging (PLC-lang#999)
Browse files Browse the repository at this point in the history
  • Loading branch information
volsa authored Nov 20, 2023
1 parent 5dac39d commit 77cd41e
Show file tree
Hide file tree
Showing 13 changed files with 401 additions and 29 deletions.
23 changes: 21 additions & 2 deletions compiler/plc_driver/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -215,13 +215,32 @@ pub fn parse_and_annotate<T: SourceContainer>(

/// Generates an IR string from a list of sources. Useful for tests or api calls
pub fn generate_to_string<T: SourceContainer>(name: &str, src: Vec<T>) -> Result<String, Diagnostic> {
generate_to_string_internal(name, src, false)
}

/// Generates an IR string from a list of sources with debug information enabled. Useful for tests or api calls
pub fn generate_to_string_debug<T: SourceContainer>(name: &str, src: Vec<T>) -> Result<String, Diagnostic> {
generate_to_string_internal(name, src, true)
}

fn generate_to_string_internal<T: SourceContainer>(
name: &str,
src: Vec<T>,
debug: bool,
) -> Result<String, Diagnostic> {
let mut diagnostician = Diagnostician::default();
let project = parse_and_annotate(name, src)?;
//Validate

// Validate
project.validate(&mut diagnostician)?;

// Generate
let context = CodegenContext::create();
let module = project.generate_single_module(&context, &CompileOptions::default())?;
let mut options = CompileOptions::default();
if debug {
options.debug_level = DebugLevel::Full;
}
let module = project.generate_single_module(&context, &options)?;

module.map(|it| it.persist_to_string()).ok_or_else(|| Diagnostic::GeneralError {
message: "Cannot generate module".to_string(),
Expand Down
15 changes: 14 additions & 1 deletion compiler/plc_source/src/source_location.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,14 @@ impl CodeSpan {
}
}

pub fn get_line_plus_one(&self) -> usize {
match self {
Self::Range(range) => range.start.line + 1,
Self::Block { local_id, .. } => *local_id,
_ => 0,
}
}

/// Gets the colmumn representation for a source location
/// If the location does not represent a line, 0 is returned
pub fn get_column(&self) -> usize {
Expand Down Expand Up @@ -181,11 +189,16 @@ impl SourceLocation {

/// Gets the line representation for a source location
/// If the location does not represent a line, the closest equivalent is returned
// That is 0 for None and the ID for id/inner spans
/// That is 0 for None and the ID for id/inner spans
pub fn get_line(&self) -> usize {
self.span.get_line()
}

/// Same as [`get_line`] but adds one to the line number if its of type [`CodeSpan::Range`].
pub fn get_line_plus_one(&self) -> usize {
self.span.get_line_plus_one()
}

/// Gets the colmumn representation for a source location
/// If the location does not represent a line, 0 is returned
pub fn get_column(&self) -> usize {
Expand Down
2 changes: 1 addition & 1 deletion compiler/plc_xml/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@ pub(crate) mod model {
pub mod variables;
}
mod reader;
pub(crate) mod serializer;
pub mod serializer;
19 changes: 19 additions & 0 deletions compiler/plc_xml/src/serializer.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#![allow(clippy::new_without_default)]

use std::collections::HashMap;

#[derive(Clone)]
Expand Down Expand Up @@ -144,6 +146,7 @@ macro_rules! newtype_impl {
};
}

// newtype_impl!(<struct name>, <xml name>, <is negatable>)
newtype_impl!(SInVariable, "inVariable", true);
newtype_impl!(SOutVariable, "outVariable", true);
newtype_impl!(SInOutVariable, "inOutVariable", true);
Expand Down Expand Up @@ -173,6 +176,8 @@ newtype_impl!(SConnector, "connector", false);
newtype_impl!(SContinuation, "continuation", false);
newtype_impl!(SJump, "jump", false);
newtype_impl!(SLabel, "label", false);
newtype_impl!(SAction, "action", false);
newtype_impl!(SActions, "actions", false);

impl SInVariable {
pub fn connect(mut self, ref_local_id: i32) -> Self {
Expand Down Expand Up @@ -258,6 +263,10 @@ impl SPou {
pub fn with_fbd(self, children: Vec<&dyn IntoNode>) -> Self {
self.child(&SBody::new().child(&YFbd::new().children(children)))
}

pub fn with_actions(self, children: Vec<&dyn IntoNode>) -> Self {
self.child(&SActions::new().children(children))
}
}

impl SBlock {
Expand Down Expand Up @@ -363,3 +372,13 @@ impl SJump {
)
}
}

impl SAction {
pub fn name(name: &'static str) -> Self {
Self::new().attribute("name", name)
}

pub fn with_fbd(self, children: Vec<&dyn IntoNode>) -> Self {
self.child(&SBody::new().child(&YFbd::new().children(children)))
}
}
27 changes: 11 additions & 16 deletions src/codegen/debug.rs
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,7 @@ impl<'ink> DebugBuilder<'ink> {
file.as_debug_info_scope(),
member_name,
file,
location.get_line().wrapping_add(1) as u32,
location.get_line_plus_one() as u32,
size.bits().into(),
alignment.bits(),
running_offset.bits().into(),
Expand All @@ -302,7 +302,7 @@ impl<'ink> DebugBuilder<'ink> {
file.as_debug_info_scope(),
name,
file,
location.get_line().wrapping_add(1) as u32,
location.get_line_plus_one() as u32,
running_offset.bits().into(),
struct_dt.get_alignment(index).bits(),
DIFlags::PUBLIC,
Expand Down Expand Up @@ -429,7 +429,7 @@ impl<'ink> DebugBuilder<'ink> {
inner_type.into(),
name,
file,
location.get_line().wrapping_add(1) as u32,
location.get_line_plus_one() as u32,
file.as_debug_info_scope(),
inner_dt.get_type_information().get_alignment(index).bits(),
);
Expand Down Expand Up @@ -484,7 +484,7 @@ impl<'ink> DebugBuilder<'ink> {
pou.get_name(),
Some(pou.get_name()), // for generics e.g. NAME__TYPE
file,
location.get_line().wrapping_add(1) as u32,
location.get_line_plus_one() as u32,
// entry for the function
ditype,
false, // TODO: what is this
Expand Down Expand Up @@ -562,7 +562,7 @@ impl<'ink> DebugBuilder<'ink> {
.get_file_name()
.map(|it| self.get_or_create_debug_file(it))
.unwrap_or_else(|| self.compile_unit.get_file());
let line = location.get_line().wrapping_add(1) as u32;
let line = location.get_line_plus_one() as u32;
let scope = scope
.get_subprogram()
.map(|it| it.as_debug_info_scope())
Expand Down Expand Up @@ -597,13 +597,8 @@ impl<'ink> Debug<'ink> for DebugBuilder<'ink> {
.get_subprogram()
.map(|it| it.as_debug_info_scope())
.unwrap_or_else(|| self.compile_unit.as_debug_info_scope());
let location = self.debug_info.create_debug_location(
self.context,
(line + 1) as u32,
column as u32,
scope,
None,
);
let location =
self.debug_info.create_debug_location(self.context, line as u32, column as u32, scope, None);
llvm.builder.set_current_debug_location(location);
}

Expand Down Expand Up @@ -696,7 +691,7 @@ impl<'ink> Debug<'ink> for DebugBuilder<'ink> {
name,
"",
file,
location.get_line().wrapping_add(1) as u32,
location.get_line_plus_one() as u32,
debug_type.into(),
false,
None,
Expand All @@ -722,7 +717,7 @@ impl<'ink> Debug<'ink> for DebugBuilder<'ink> {
.get_file_name()
.map(|it| self.get_or_create_debug_file(it))
.unwrap_or_else(|| self.compile_unit.get_file());
let line = location.get_line().wrapping_add(1) as u32;
let line = location.get_line_plus_one() as u32;

let scope = scope
.get_subprogram()
Expand Down Expand Up @@ -756,7 +751,7 @@ impl<'ink> Debug<'ink> for DebugBuilder<'ink> {
.get_file_name()
.map(|it| self.get_or_create_debug_file(it))
.unwrap_or_else(|| self.compile_unit.get_file());
let line = location.get_line().wrapping_add(1) as u32;
let line = location.get_line_plus_one() as u32;
let scope = scope
.get_subprogram()
.map(|it| it.as_debug_info_scope())
Expand Down Expand Up @@ -790,7 +785,7 @@ impl<'ink> Debug<'ink> for DebugBuilder<'ink> {
.get_file_name()
.map(|it| self.get_or_create_debug_file(it))
.unwrap_or_else(|| self.compile_unit.get_file());
let line = pou.get_location().get_line().wrapping_add(1) as u32;
let line = pou.get_location().get_line_plus_one() as u32;
let debug_variable = self.debug_info.create_parameter_variable(
scope,
pou.get_name(),
Expand Down
2 changes: 1 addition & 1 deletion src/codegen/generators/expression_generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ impl<'ink, 'b> ExpressionCodeGenerator<'ink, 'b> {
fn register_debug_location(&self, statement: &AstNode) {
let function_context =
self.function_context.expect("Cannot generate debug info without function context");
let line = statement.get_location().get_line();
let line = statement.get_location().get_line_plus_one();
let column = statement.get_location().get_column();
self.debug.set_debug_location(self.llvm, &function_context.function, line, column);
}
Expand Down
6 changes: 4 additions & 2 deletions src/codegen/generators/pou_generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -297,8 +297,10 @@ impl<'ink, 'cg> PouGenerator<'ink, 'cg> {
let (line, column) = implementation
.statements
.first()
.map(|it| (it.get_location().get_line(), it.get_location().get_column()))
.or_else(|| Some((implementation.location.get_line(), implementation.location.get_column())))
.map(|it| (it.get_location().get_line_plus_one(), it.get_location().get_column()))
.or_else(|| {
Some((implementation.location.get_line_plus_one(), implementation.location.get_column()))
})
// .or_else(|| Some(implementation.location.get_start()))
.unwrap();
debug.set_debug_location(&self.llvm, &current_function, line, column);
Expand Down
15 changes: 10 additions & 5 deletions src/codegen/generators/statement_generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,8 +129,7 @@ impl<'a, 'b> StatementCodeGenerator<'a, 'b> {
}
AstStatement::ReturnStatement(ReturnStatement { condition }) => match condition {
Some(condition) => {
self.register_debug_location(statement);
self.generate_conditional_return(condition)?;
self.generate_conditional_return(statement, condition)?;
}
None => {
self.register_debug_location(statement);
Expand Down Expand Up @@ -276,7 +275,7 @@ impl<'a, 'b> StatementCodeGenerator<'a, 'b> {
}

fn register_debug_location(&self, statement: &AstNode) {
let line = statement.get_location().get_line();
let line = statement.get_location().get_line_plus_one();
let column = statement.get_location().get_column();
self.debug.set_debug_location(self.llvm, &self.function_context.function, line, column);
}
Expand Down Expand Up @@ -812,8 +811,14 @@ impl<'a, 'b> StatementCodeGenerator<'a, 'b> {

/// Generates LLVM IR for conditional returns, which return if a given condition evaluates to true and
/// does nothing otherwise.
pub fn generate_conditional_return(&'a self, condition: &AstNode) -> Result<(), Diagnostic> {
pub fn generate_conditional_return(
&'a self,
statement: &AstNode,
condition: &AstNode,
) -> Result<(), Diagnostic> {
let expression_generator = self.create_expr_generator();

self.register_debug_location(condition);
let condition = expression_generator.generate_expression(condition)?;

let then_block = self.llvm.context.append_basic_block(self.function_context.function, "then_block");
Expand All @@ -826,8 +831,8 @@ impl<'a, 'b> StatementCodeGenerator<'a, 'b> {
);

self.llvm.builder.position_at_end(then_block);
self.register_debug_location(statement);
self.generate_return_statement()?;

self.llvm.builder.position_at_end(else_block);

Ok(())
Expand Down
Loading

0 comments on commit 77cd41e

Please sign in to comment.