diff --git a/compiler/plc_driver/src/cli.rs b/compiler/plc_driver/src/cli.rs index 46f0dc2bae..960b88fb87 100644 --- a/compiler/plc_driver/src/cli.rs +++ b/compiler/plc_driver/src/cli.rs @@ -213,6 +213,12 @@ pub struct CompileParameters { #[clap(name = "check", long, help = "Check only, do not generate any output", global = true)] pub check_only: bool, + #[clap( + long, + help = "Emit a binary with specific compilation information, suitable for online changes when ran under a conforming runtime" + )] + pub online_change: bool, + #[clap(subcommand)] pub commands: Option, } diff --git a/compiler/plc_driver/src/lib.rs b/compiler/plc_driver/src/lib.rs index 9564b9e449..67460c6052 100644 --- a/compiler/plc_driver/src/lib.rs +++ b/compiler/plc_driver/src/lib.rs @@ -19,8 +19,8 @@ use std::{ use cli::{CompileParameters, ParameterError, SubCommands}; use pipelines::AnnotatedProject; use plc::{ - codegen::CodegenContext, linker::LinkerType, output::FormatOption, ConfigFormat, DebugLevel, - ErrorFormat, OptimizationLevel, Target, Threads, + codegen::CodegenContext, linker::LinkerType, output::FormatOption, ConfigFormat, DebugLevel, ErrorFormat, + OnlineChange, OptimizationLevel, Target, Threads, }; use plc_diagnostics::{diagnostician::Diagnostician, diagnostics::Diagnostic}; @@ -56,6 +56,7 @@ pub struct CompileOptions { pub error_format: ErrorFormat, pub debug_level: DebugLevel, pub single_module: bool, + pub online_change: OnlineChange, } impl Default for CompileOptions { @@ -71,6 +72,7 @@ impl Default for CompileOptions { error_format: ErrorFormat::None, debug_level: DebugLevel::None, single_module: false, + online_change: OnlineChange::Disabled, } } } @@ -182,6 +184,11 @@ pub fn get_compilation_context + AsRef + Debug>( error_format: compile_parameters.error_format, debug_level: compile_parameters.debug_level(), single_module: compile_parameters.single_module, + online_change: if compile_parameters.online_change { + OnlineChange::Enabled + } else { + OnlineChange::Disabled + }, }; let libraries = diff --git a/compiler/plc_driver/src/pipelines.rs b/compiler/plc_driver/src/pipelines.rs index 72d86b0ff8..80dd6c7766 100644 --- a/compiler/plc_driver/src/pipelines.rs +++ b/compiler/plc_driver/src/pipelines.rs @@ -330,6 +330,7 @@ impl AnnotatedProject { compile_options.got_layout_file.clone().zip(compile_options.got_layout_format), compile_options.optimization, compile_options.debug_level, + compile_options.online_change, ); //Create a types codegen, this contains all the type declarations //Associate the index type with LLVM types diff --git a/src/codegen.rs b/src/codegen.rs index 8bf1eb116f..5000bad2fe 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -21,7 +21,7 @@ use self::{ use crate::{ output::FormatOption, resolver::{AstAnnotations, Dependency, StringLiterals}, - ConfigFormat, DebugLevel, OptimizationLevel, Target, + ConfigFormat, DebugLevel, OnlineChange, OptimizationLevel, Target, }; use super::index::*; @@ -75,6 +75,8 @@ pub struct CodeGen<'ink> { pub module: Module<'ink>, /// the debugging module creates debug information at appropriate locations pub debug: DebugBuilderEnum<'ink>, + /// Whether we are generating a hot-reloadable binary or not + pub online_change: OnlineChange, pub got_layout_file: Option<(String, ConfigFormat)>, @@ -98,11 +100,18 @@ impl<'ink> CodeGen<'ink> { got_layout_file: Option<(String, ConfigFormat)>, optimization_level: OptimizationLevel, debug_level: DebugLevel, + online_change: OnlineChange, ) -> CodeGen<'ink> { let module = context.create_module(module_location); module.set_source_file_name(module_location); let debug = debug::DebugBuilderEnum::new(context, &module, root, optimization_level, debug_level); - CodeGen { module, debug, got_layout_file, module_location: module_location.to_string() } + CodeGen { + module, + debug, + got_layout_file, + module_location: module_location.to_string(), + online_change, + } } pub fn generate_llvm_index( @@ -224,6 +233,7 @@ impl<'ink> CodeGen<'ink> { annotations, &index, &mut self.debug, + self.online_change, )?; let llvm = Llvm::new(context, context.create_builder()); index.merge(llvm_impl_index); @@ -286,7 +296,8 @@ impl<'ink> CodeGen<'ink> { ) -> Result, Diagnostic> { //generate all pous let llvm = Llvm::new(context, context.create_builder()); - let pou_generator = PouGenerator::new(llvm, global_index, annotations, &llvm_index); + let pou_generator = + PouGenerator::new(llvm, global_index, annotations, &llvm_index, self.online_change); //Generate the POU stubs in the first go to make sure they can be referenced. for implementation in &unit.implementations { diff --git a/src/codegen/generators/pou_generator.rs b/src/codegen/generators/pou_generator.rs index cada91f3b1..d254c56763 100644 --- a/src/codegen/generators/pou_generator.rs +++ b/src/codegen/generators/pou_generator.rs @@ -16,6 +16,7 @@ use crate::{ index::{self, ImplementationType}, resolver::{AstAnnotations, Dependency}, typesystem::{DataType, DataTypeInformation, VarArgs, DINT_TYPE}, + OnlineChange, }; /// The pou_generator contains functions to generate the code for POUs (PROGRAM, FUNCTION, FUNCTION_BLOCK) @@ -49,6 +50,7 @@ pub struct PouGenerator<'ink, 'cg> { index: &'cg Index, annotations: &'cg AstAnnotations, llvm_index: &'cg LlvmTypedIndex<'ink>, + online_change: OnlineChange, } /// Creates opaque implementations for all callable items in the index @@ -61,9 +63,10 @@ pub fn generate_implementation_stubs<'ink>( annotations: &AstAnnotations, types_index: &LlvmTypedIndex<'ink>, debug: &mut DebugBuilderEnum<'ink>, + online_change: OnlineChange, ) -> Result, Diagnostic> { let mut llvm_index = LlvmTypedIndex::default(); - let pou_generator = PouGenerator::new(llvm, index, annotations, types_index); + let pou_generator = PouGenerator::new(llvm, index, annotations, types_index, online_change); let implementations = dependencies .into_iter() .filter_map(|it| { @@ -150,8 +153,9 @@ impl<'ink, 'cg> PouGenerator<'ink, 'cg> { index: &'cg Index, annotations: &'cg AstAnnotations, llvm_index: &'cg LlvmTypedIndex<'ink>, + online_change: OnlineChange, ) -> PouGenerator<'ink, 'cg> { - PouGenerator { llvm, index, annotations, llvm_index } + PouGenerator { llvm, index, annotations, llvm_index, online_change } } fn mangle_function(&self, implementation: &ImplementationIndexEntry) -> Result { @@ -286,8 +290,10 @@ impl<'ink, 'cg> PouGenerator<'ink, 'cg> { let curr_f = module.add_function(implementation.get_call_name(), function_declaration, None); - let section_name = self.mangle_function(implementation)?; - curr_f.set_section(Some(§ion_name)); + if self.online_change == OnlineChange::Enabled { + let section_name = self.mangle_function(implementation)?; + curr_f.set_section(Some(§ion_name)); + } let pou_name = implementation.get_call_name(); if let Some(pou) = self.index.find_pou(pou_name) { diff --git a/src/lib.rs b/src/lib.rs index 1092512aae..715c1639b1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -176,6 +176,12 @@ pub enum DebugLevel { Full(usize), } +#[derive(Debug, Copy, Clone, PartialEq)] +pub enum OnlineChange { + Enabled, + Disabled, +} + impl From for inkwell::OptimizationLevel { fn from(val: OptimizationLevel) -> Self { match val { diff --git a/src/test_utils.rs b/src/test_utils.rs index 6b153a4c4e..9f871ebcce 100644 --- a/src/test_utils.rs +++ b/src/test_utils.rs @@ -164,6 +164,7 @@ pub mod tests { None, crate::OptimizationLevel::None, debug_level, + crate::OnlineChange::Disabled, ); let annotations = AstAnnotations::new(annotations, id_provider.next_id()); @@ -239,6 +240,7 @@ pub mod tests { None, crate::OptimizationLevel::None, debug_level, + crate::OnlineChange::Disabled, ); let got_layout = Mutex::new(None);