Skip to content

Commit 16b756f

Browse files
authored
Merge pull request #1319 from PLC-lang/embecosm-online-chane
Initial online change support - Adds an online change flag - Generates a GOT and moves references to an indirection when online change is active.
2 parents 014a437 + 85ab8df commit 16b756f

File tree

448 files changed

+4944
-4199
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

448 files changed

+4944
-4199
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,6 @@ tempfile = "3"
5656
encoding_rs.workspace = true
5757
encoding_rs_io.workspace = true
5858

59-
6059
[lib]
6160
name = "rusty"
6261
path = "src/lib.rs"

compiler/plc_driver/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ plc_index = { path = "../plc_index" }
1717

1818
serde = { version = "1.0", features = ["derive"] }
1919
serde_json = "1"
20+
toml = "0.5"
2021
clap = { version = "3.0", features = ["derive"] }
2122
rayon = "1.6.1"
2223
tempfile = "3"

compiler/plc_driver/src/cli.rs

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ use encoding_rs::Encoding;
55
use plc_diagnostics::diagnostics::{diagnostics_registry::DiagnosticsConfiguration, Diagnostic};
66
use std::{env, ffi::OsStr, num::ParseIntError, path::PathBuf};
77

8-
use plc::{output::FormatOption, ConfigFormat, DebugLevel, ErrorFormat, Target, Threads};
8+
use plc::output::FormatOption;
9+
use plc::{ConfigFormat, DebugLevel, ErrorFormat, Target, Threads, DEFAULT_GOT_LAYOUT_FILE};
910

1011
pub type ParameterError = clap::Error;
1112

@@ -109,6 +110,22 @@ pub struct CompileParameters {
109110
) ]
110111
pub hardware_config: Option<String>,
111112

113+
#[clap(
114+
name = "got-layout-file",
115+
long,
116+
global = true,
117+
help = "Obtain information about the current custom GOT layout from the given file if it exists.
118+
Save information about the generated custom GOT layout to the given file.
119+
Format is detected by extension.
120+
Supported formats : json, toml",
121+
default_value = DEFAULT_GOT_LAYOUT_FILE,
122+
parse(try_from_str = validate_config),
123+
// FIXME: For some reason, this does not work at the moment but it really should
124+
// The binary behaves as expected but the tests fail
125+
// requires = "online-change"
126+
) ]
127+
pub got_layout_file: String,
128+
112129
#[clap(
113130
name = "optimization",
114131
long,
@@ -202,6 +219,12 @@ pub struct CompileParameters {
202219
#[clap(name = "check", long, help = "Check only, do not generate any output", global = true)]
203220
pub check_only: bool,
204221

222+
#[clap(
223+
long,
224+
help = "Emit a binary with specific compilation information, suitable for online changes when ran under a conforming runtime"
225+
)]
226+
pub online_change: bool,
227+
205228
#[clap(subcommand)]
206229
pub commands: Option<SubCommands>,
207230
}
@@ -388,6 +411,11 @@ impl CompileParameters {
388411
self.hardware_config.as_deref().and_then(get_config_format)
389412
}
390413

414+
pub fn got_layout_format(&self) -> ConfigFormat {
415+
// It is safe to unwrap here, since the provided argument to `--got-online-change` has been checked with `validate_config`
416+
get_config_format(&self.got_layout_file).unwrap()
417+
}
418+
391419
/// Returns the location where the build artifacts should be stored / output
392420
pub fn get_build_location(&self) -> Option<PathBuf> {
393421
match &self.commands {

compiler/plc_driver/src/lib.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ use std::{
1919

2020
use cli::{CompileParameters, ParameterError, SubCommands};
2121
use plc::{
22-
codegen::CodegenContext, linker::LinkerType, output::FormatOption, DebugLevel, ErrorFormat,
22+
codegen::CodegenContext, linker::LinkerType, output::FormatOption, DebugLevel, ErrorFormat, OnlineChange,
2323
OptimizationLevel, Target, Threads,
2424
};
2525

@@ -54,6 +54,7 @@ pub struct CompileOptions {
5454
pub error_format: ErrorFormat,
5555
pub debug_level: DebugLevel,
5656
pub single_module: bool,
57+
pub online_change: OnlineChange,
5758
}
5859

5960
impl Default for CompileOptions {
@@ -67,6 +68,7 @@ impl Default for CompileOptions {
6768
error_format: ErrorFormat::None,
6869
debug_level: DebugLevel::None,
6970
single_module: false,
71+
online_change: OnlineChange::Disabled,
7072
}
7173
}
7274
}
@@ -176,6 +178,14 @@ pub fn get_compilation_context<T: AsRef<str> + AsRef<OsStr> + Debug>(
176178
error_format: compile_parameters.error_format,
177179
debug_level: compile_parameters.debug_level(),
178180
single_module: compile_parameters.single_module,
181+
online_change: if compile_parameters.online_change {
182+
OnlineChange::Enabled {
183+
file_name: compile_parameters.got_layout_file.clone(),
184+
format: compile_parameters.got_layout_format(),
185+
}
186+
} else {
187+
OnlineChange::Disabled
188+
},
179189
};
180190

181191
let libraries =

compiler/plc_driver/src/pipelines.rs

Lines changed: 81 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
use std::{
2+
collections::HashMap,
23
env,
34
fs::{self, File},
45
io::Write,
56
path::{Path, PathBuf},
7+
sync::Mutex,
68
};
79

810
use crate::{CompileOptions, LinkOptions};
@@ -22,7 +24,7 @@ use plc::{
2224
TypeAnnotator,
2325
},
2426
validation::Validator,
25-
ConfigFormat, Target,
27+
ConfigFormat, OnlineChange, Target,
2628
};
2729
use plc_diagnostics::{
2830
diagnostician::Diagnostician,
@@ -36,6 +38,42 @@ use project::{
3638
use rayon::prelude::*;
3739
use source_code::{source_location::SourceLocation, SourceContainer};
3840

41+
use serde_json;
42+
use toml;
43+
44+
pub fn read_got_layout(location: &str, format: ConfigFormat) -> Result<HashMap<String, u64>, Diagnostic> {
45+
if !Path::new(location).is_file() {
46+
// Assume if the file doesn't exist that there is no existing GOT layout yet. write_got_layout will handle
47+
// creating our file when we want to.
48+
return Ok(HashMap::new());
49+
}
50+
51+
let s = fs::read_to_string(location)
52+
.map_err(|_| Diagnostic::new("GOT layout could not be read from file"))?;
53+
match format {
54+
ConfigFormat::JSON => serde_json::from_str(&s)
55+
.map_err(|_| Diagnostic::new("Could not deserialize GOT layout from JSON")),
56+
ConfigFormat::TOML => {
57+
toml::de::from_str(&s).map_err(|_| Diagnostic::new("Could not deserialize GOT layout from TOML"))
58+
}
59+
}
60+
}
61+
62+
fn write_got_layout(
63+
got_entries: HashMap<String, u64>,
64+
location: &str,
65+
format: ConfigFormat,
66+
) -> Result<(), Diagnostic> {
67+
let s = match format {
68+
ConfigFormat::JSON => serde_json::to_string(&got_entries)
69+
.map_err(|_| Diagnostic::new("Could not serialize GOT layout to JSON"))?,
70+
ConfigFormat::TOML => toml::ser::to_string(&got_entries)
71+
.map_err(|_| Diagnostic::new("Could not serialize GOT layout to TOML"))?,
72+
};
73+
74+
fs::write(location, s).map_err(|_| Diagnostic::new("GOT layout could not be written to file"))
75+
}
76+
3977
///Represents a parsed project
4078
///For this struct to be built, the project would have been parsed correctly and an AST would have
4179
///been generated
@@ -271,11 +309,18 @@ impl<T: SourceContainer + Sync> AnnotatedProject<T> {
271309
}
272310

273311
pub fn codegen_to_string(&self, compile_options: &CompileOptions) -> Result<Vec<String>, Diagnostic> {
312+
let got_layout = if let OnlineChange::Enabled { file_name, format } = &compile_options.online_change {
313+
read_got_layout(file_name, *format)?
314+
} else {
315+
HashMap::default()
316+
};
317+
let got_layout = Mutex::new(got_layout);
318+
274319
self.units
275320
.iter()
276321
.map(|AnnotatedUnit { unit, dependencies, literals }| {
277322
let context = CodegenContext::create();
278-
self.generate_module(&context, compile_options, unit, dependencies, literals)
323+
self.generate_module(&context, compile_options, unit, dependencies, literals, &got_layout)
279324
.map(|it| it.persist_to_string())
280325
})
281326
.collect()
@@ -286,11 +331,18 @@ impl<T: SourceContainer + Sync> AnnotatedProject<T> {
286331
context: &'ctx CodegenContext,
287332
compile_options: &CompileOptions,
288333
) -> Result<Option<GeneratedModule<'ctx>>, Diagnostic> {
334+
let got_layout = if let OnlineChange::Enabled { file_name, format } = &compile_options.online_change {
335+
read_got_layout(file_name, *format)?
336+
} else {
337+
HashMap::default()
338+
};
339+
let got_layout = Mutex::new(got_layout);
340+
289341
let Some(module) = self
290342
.units
291343
.iter()
292344
.map(|AnnotatedUnit { unit, dependencies, literals }| {
293-
self.generate_module(context, compile_options, unit, dependencies, literals)
345+
self.generate_module(context, compile_options, unit, dependencies, literals, &got_layout)
294346
})
295347
.reduce(|a, b| {
296348
let a = a?;
@@ -310,13 +362,16 @@ impl<T: SourceContainer + Sync> AnnotatedProject<T> {
310362
unit: &CompilationUnit,
311363
dependencies: &FxIndexSet<Dependency>,
312364
literals: &StringLiterals,
365+
got_layout: &Mutex<HashMap<String, u64>>,
313366
) -> Result<GeneratedModule<'ctx>, Diagnostic> {
314367
let mut code_generator = plc::codegen::CodeGen::new(
315368
context,
316369
compile_options.root.as_deref(),
317370
&unit.file_name,
318371
compile_options.optimization,
319372
compile_options.debug_level,
373+
//FIXME don't clone here
374+
compile_options.online_change.clone(),
320375
);
321376
//Create a types codegen, this contains all the type declarations
322377
//Associate the index type with LLVM types
@@ -326,8 +381,9 @@ impl<T: SourceContainer + Sync> AnnotatedProject<T> {
326381
literals,
327382
dependencies,
328383
&self.index,
384+
got_layout,
329385
)?;
330-
code_generator.generate(context, unit, &self.annotations, &self.index, &llvm_index)
386+
code_generator.generate(context, unit, &self.annotations, &self.index, llvm_index)
331387
}
332388

333389
pub fn codegen_single_module<'ctx>(
@@ -372,6 +428,14 @@ impl<T: SourceContainer + Sync> AnnotatedProject<T> {
372428
});
373429
ensure_compile_dirs(targets, &compile_directory)?;
374430
let targets = if targets.is_empty() { &[Target::System] } else { targets };
431+
432+
let got_layout = if let OnlineChange::Enabled { file_name, format } = &compile_options.online_change {
433+
read_got_layout(file_name, *format)?
434+
} else {
435+
HashMap::default()
436+
};
437+
let got_layout = Mutex::new(got_layout);
438+
375439
let res = targets
376440
.par_iter()
377441
.map(|target| {
@@ -409,8 +473,15 @@ impl<T: SourceContainer + Sync> AnnotatedProject<T> {
409473
};
410474

411475
let context = CodegenContext::create(); //Create a build location for the generated object files
412-
let module =
413-
self.generate_module(&context, compile_options, unit, dependencies, literals)?;
476+
let module = self.generate_module(
477+
&context,
478+
compile_options,
479+
unit,
480+
dependencies,
481+
literals,
482+
&got_layout,
483+
)?;
484+
414485
module
415486
.persist(
416487
Some(&compile_directory),
@@ -429,6 +500,10 @@ impl<T: SourceContainer + Sync> AnnotatedProject<T> {
429500
})
430501
.collect::<Result<Vec<_>, Diagnostic>>()?;
431502

503+
if let OnlineChange::Enabled { file_name, format } = &compile_options.online_change {
504+
write_got_layout(got_layout.into_inner().unwrap(), file_name, *format)?;
505+
}
506+
432507
Ok(res)
433508
}
434509

compiler/plc_driver/src/tests/snapshots/plc_driver__tests__external_files__external_file_function_call.snap

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ expression: "results.join(\"\\n\")"
55
; ModuleID = 'main.st'
66
source_filename = "main.st"
77

8-
define i16 @main() section "fn-$RUSTY$main:i16" {
8+
define i16 @main() {
99
entry:
1010
%main = alloca i16, align 2
1111
store i16 0, i16* %main, align 2
@@ -14,17 +14,17 @@ entry:
1414
ret i16 %main_ret
1515
}
1616

17-
declare i16 @external() section "fn-$RUSTY$external:i16"
17+
declare i16 @external()
1818

1919
; ModuleID = 'external.st'
2020
source_filename = "external.st"
2121

22-
declare i16 @external() section "fn-$RUSTY$external:i16"
22+
declare i16 @external()
2323

2424
; ModuleID = '__init___TestProject'
2525
source_filename = "__init___TestProject"
2626

27-
define void @__init___TestProject() section "fn-$RUSTY$__init___TestProject:v" {
27+
define void @__init___TestProject() {
2828
entry:
2929
ret void
3030
}

compiler/plc_driver/src/tests/snapshots/plc_driver__tests__external_files__external_file_global_var.snap

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@ expression: "results.join(\"\\n\")"
55
; ModuleID = 'main.st'
66
source_filename = "main.st"
77

8-
@x = external global i16, section "var-$RUSTY$x:i16"
9-
@y = external global i16, section "var-$RUSTY$y:i16"
8+
@x = external global i16
9+
@y = external global i16
1010

11-
define i16 @main() section "fn-$RUSTY$main:i16" {
11+
define i16 @main() {
1212
entry:
1313
%main = alloca i16, align 2
1414
store i16 0, i16* %main, align 2
@@ -19,20 +19,20 @@ entry:
1919
ret i16 %main_ret
2020
}
2121

22-
declare i16 @external() section "fn-$RUSTY$external:i16"
22+
declare i16 @external()
2323

2424
; ModuleID = 'external.st'
2525
source_filename = "external.st"
2626

27-
@x = external global i16, section "var-$RUSTY$x:i16"
28-
@y = external global i16, section "var-$RUSTY$y:i16"
27+
@x = external global i16
28+
@y = external global i16
2929

30-
declare i16 @external() section "fn-$RUSTY$external:i16"
30+
declare i16 @external()
3131

3232
; ModuleID = '__init___TestProject'
3333
source_filename = "__init___TestProject"
3434

35-
define void @__init___TestProject() section "fn-$RUSTY$__init___TestProject:v" {
35+
define void @__init___TestProject() {
3636
entry:
3737
ret void
3838
}

0 commit comments

Comments
 (0)