Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add optimization parameters #473

Merged
merged 3 commits into from
Mar 17, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion book/src/using_rusty.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ for that and link with libc when we're done. This program can also be found at
done. Otherwise, the program will most likely crash (because it tries to return to a function that never
existed).

```st
```iecst
@EXTERNAL FUNCTION puts : DINT
VAR_INPUT
text : STRING;
Expand All @@ -59,6 +59,18 @@ Compiling with rusty is very easy. If you just want to build an object file, the
rustyc -c hello_world.st -o hello_world.o
```

### Optimization
`rustyc` offers 4 levels of optimization which correspond to the levels established by llvm respectively [clang](https://clang.llvm.org/docs/CommandGuide/clang.html#code-generation-options) (`none` to `aggressive`, respectively `-O0` to `-O3`).

To use an optimization, the flag `-O` or `--optimization` is required:

- `rustyc -c "**/*.st" -O none`
- `rustyc -c "**/*.st" -O less`
- `rustyc -c "**/*.st" -O default`
- `rustyc -c "**/*.st" -O aggressive`

By default `rustyc` will use `default` which corresponds to clang's `-O2`.

### Linking an executable
Instead, you can also compile this into an executable and run it:
```bash
Expand Down
50 changes: 49 additions & 1 deletion src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,16 @@ pub struct CompileParameters {
parse(try_from_str = validate_config)
) ]
pub hardware_config: Option<String>,

#[clap(
name = "optimization",
long,
short = 'O',
help = "Optimization level",
arg_enum,
default_value = "default"
)]
pub optimization: crate::OptimizationLevel,
}

fn parse_encoding(encoding: &str) -> Result<&'static Encoding, String> {
Expand Down Expand Up @@ -211,7 +221,7 @@ impl CompileParameters {
#[cfg(test)]
mod cli_tests {
use super::CompileParameters;
use crate::{ConfigFormat, FormatOption};
use crate::{ConfigFormat, FormatOption, OptimizationLevel};
use clap::ErrorKind;
use pretty_assertions::assert_eq;

Expand Down Expand Up @@ -329,6 +339,44 @@ mod cli_tests {
assert_eq!(parameters.target, Some("x86_64-linux-gnu".to_string()));
}

#[test]
fn test_optimization_levels() {
let parameters = CompileParameters::parse(vec_of_strings!("alpha.st")).unwrap();

assert_eq!(parameters.optimization, OptimizationLevel::Default);
let parameters = CompileParameters::parse(vec_of_strings!("alpha.st", "-Onone")).unwrap();

assert_eq!(parameters.optimization, OptimizationLevel::None);
let parameters =
CompileParameters::parse(vec_of_strings!("alpha.st", "--optimization", "none"))
.unwrap();
assert_eq!(parameters.optimization, OptimizationLevel::None);

let parameters = CompileParameters::parse(vec_of_strings!("alpha.st", "-Oless")).unwrap();

assert_eq!(parameters.optimization, OptimizationLevel::Less);
let parameters =
CompileParameters::parse(vec_of_strings!("alpha.st", "--optimization", "less"))
.unwrap();
assert_eq!(parameters.optimization, OptimizationLevel::Less);
let parameters =
CompileParameters::parse(vec_of_strings!("alpha.st", "-Odefault")).unwrap();

assert_eq!(parameters.optimization, OptimizationLevel::Default);
let parameters =
CompileParameters::parse(vec_of_strings!("alpha.st", "--optimization", "default"))
.unwrap();
assert_eq!(parameters.optimization, OptimizationLevel::Default);
let parameters =
CompileParameters::parse(vec_of_strings!("alpha.st", "-Oaggressive")).unwrap();

assert_eq!(parameters.optimization, OptimizationLevel::Aggressive);
let parameters =
CompileParameters::parse(vec_of_strings!("alpha.st", "--optimization", "aggressive"))
.unwrap();
assert_eq!(parameters.optimization, OptimizationLevel::Aggressive);
}

#[test]
fn test_default_format() {
let parameters = CompileParameters::parse(vec_of_strings!("alpha.st", "--ir")).unwrap();
Expand Down
48 changes: 40 additions & 8 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ pub struct CompileOptions {
pub format: FormatOption,
pub output: String,
pub target: Option<String>,
pub optimization: OptimizationLevel,
}

pub struct LinkOptions {
Expand All @@ -110,6 +111,25 @@ struct ConfigurationOptions {
output: String,
}

#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, ArgEnum)]
pub enum OptimizationLevel {
None,
Less,
Default,
Aggressive,
}

impl From<OptimizationLevel> for inkwell::OptimizationLevel {
fn from(val: OptimizationLevel) -> Self {
match val {
OptimizationLevel::None => inkwell::OptimizationLevel::None,
OptimizationLevel::Less => inkwell::OptimizationLevel::Less,
OptimizationLevel::Default => inkwell::OptimizationLevel::Default,
OptimizationLevel::Aggressive => inkwell::OptimizationLevel::Aggressive,
}
}
}

/// A struct representing the result of a compilation
#[derive(Default)]
pub struct CompileResult {
Expand Down Expand Up @@ -239,6 +259,7 @@ fn persist_to_obj(
output: &str,
reloc: RelocMode,
triple: &TargetTriple,
optimization: OptimizationLevel,
) -> Result<(), Diagnostic> {
let initialization_config = &InitializationConfig::default();
Target::initialize_all(initialization_config);
Expand All @@ -255,8 +276,7 @@ fn persist_to_obj(
//TODO : Add cpu features as optionals
"generic", //TargetMachine::get_host_cpu_name().to_string().as_str(),
"", //TargetMachine::get_host_cpu_features().to_string().as_str(),
//TODO Optimisation as parameter
inkwell::OptimizationLevel::Default,
optimization.into(),
reloc,
CodeModel::Default,
)
Expand All @@ -282,8 +302,9 @@ pub fn persist_as_static_obj(
codegen: CodeGen,
output: &str,
target: &TargetTriple,
optimization: OptimizationLevel,
) -> Result<(), Diagnostic> {
persist_to_obj(codegen, output, RelocMode::Default, target)
persist_to_obj(codegen, output, RelocMode::Default, target, optimization)
}

/// Persists a given LLVM module to a shared postiion indepedent object and saves the output.
Expand All @@ -298,8 +319,9 @@ pub fn persist_to_shared_pic_object(
codegen: CodeGen,
output: &str,
target: &TargetTriple,
optimization: OptimizationLevel,
) -> Result<(), Diagnostic> {
persist_to_obj(codegen, output, RelocMode::PIC, target)
persist_to_obj(codegen, output, RelocMode::PIC, target, optimization)
}

/// Persists the given LLVM module to a dynamic non PIC object and saves the output.
Expand All @@ -313,8 +335,15 @@ pub fn persist_to_shared_object(
codegen: CodeGen,
output: &str,
target: &TargetTriple,
optimization: OptimizationLevel,
) -> Result<(), Diagnostic> {
persist_to_obj(codegen, output, RelocMode::DynamicNoPic, target)
persist_to_obj(
codegen,
output,
RelocMode::DynamicNoPic,
target,
optimization,
)
}

///
Expand Down Expand Up @@ -521,6 +550,7 @@ pub fn build_with_params(parameters: CompileParameters) -> Result<(), Diagnostic
output,
target: parameters.target,
format: out_format,
optimization: parameters.optimization,
};

let link_options = if !parameters.skip_linking {
Expand Down Expand Up @@ -600,6 +630,7 @@ pub fn build(
&compile_options.output,
compile_options.format,
target,
compile_options.optimization,
)?);

Ok(CompileResult { index, objects })
Expand All @@ -610,13 +641,14 @@ pub fn persist(
output: &str,
out_format: FormatOption,
target: &TargetTriple,
optimization: OptimizationLevel,
) -> Result<FilePath, Diagnostic> {
match out_format {
FormatOption::Static | FormatOption::Relocatable => {
persist_as_static_obj(input, output, target)
persist_as_static_obj(input, output, target, optimization)
}
FormatOption::Shared => persist_to_shared_object(input, output, target),
FormatOption::PIC => persist_to_shared_pic_object(input, output, target),
FormatOption::Shared => persist_to_shared_object(input, output, target, optimization),
FormatOption::PIC => persist_to_shared_pic_object(input, output, target, optimization),
FormatOption::Bitcode => persist_to_bitcode(input, output),
FormatOption::IR => persist_to_ir(input, output),
}?;
Expand Down
5 changes: 5 additions & 0 deletions tests/integration/external_files.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ fn compile_all(name: &str, encoding: Option<&'static Encoding>) {
format: rusty::FormatOption::IR,
output: out.clone(),
target: None,
optimization: rusty::OptimizationLevel::Default,
},
encoding,
&target,
Expand All @@ -34,6 +35,7 @@ fn compile_all(name: &str, encoding: Option<&'static Encoding>) {
format: rusty::FormatOption::Bitcode,
output: out.clone(),
target: None,
optimization: rusty::OptimizationLevel::Default,
},
encoding,
&target,
Expand All @@ -47,6 +49,7 @@ fn compile_all(name: &str, encoding: Option<&'static Encoding>) {
format: rusty::FormatOption::Shared,
output: out.clone(),
target: None,
optimization: rusty::OptimizationLevel::Default,
},
encoding,
&target,
Expand All @@ -60,6 +63,7 @@ fn compile_all(name: &str, encoding: Option<&'static Encoding>) {
format: rusty::FormatOption::PIC,
output: out.clone(),
target: None,
optimization: rusty::OptimizationLevel::Default,
},
encoding,
&target,
Expand All @@ -73,6 +77,7 @@ fn compile_all(name: &str, encoding: Option<&'static Encoding>) {
format: rusty::FormatOption::Static,
output: out.clone(),
target: None,
optimization: rusty::OptimizationLevel::Default,
},
encoding,
&target,
Expand Down
9 changes: 9 additions & 0 deletions tests/integration/linking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ fn link_as_shared_object() {
output: out2.clone(),
format: FormatOption::Shared,
target: TARGET.map(String::from),
optimization: rusty::OptimizationLevel::Default,
},
None,
&triple,
Expand All @@ -46,6 +47,7 @@ fn link_as_shared_object() {
output: out1.clone(),
format: FormatOption::Shared,
target: TARGET.map(String::from),
optimization: rusty::OptimizationLevel::Default,
},
None,
&triple,
Expand Down Expand Up @@ -94,6 +96,7 @@ fn link_as_pic_object() {
output: out2.clone(),
format: FormatOption::PIC,
target: TARGET.map(String::from),
optimization: rusty::OptimizationLevel::Default,
},
None,
&triple,
Expand All @@ -108,6 +111,7 @@ fn link_as_pic_object() {
output: out1.clone(),
format: FormatOption::PIC,
target: TARGET.map(String::from),
optimization: rusty::OptimizationLevel::Default,
},
None,
&triple,
Expand Down Expand Up @@ -156,6 +160,7 @@ fn link_as_static_object() {
output: out2.clone(),
format: FormatOption::Static,
target: TARGET.map(String::from),
optimization: rusty::OptimizationLevel::Default,
},
None,
&triple,
Expand All @@ -170,6 +175,7 @@ fn link_as_static_object() {
output: out1.clone(),
format: FormatOption::Static,
target: TARGET.map(String::from),
optimization: rusty::OptimizationLevel::Default,
},
None,
&triple,
Expand Down Expand Up @@ -218,6 +224,7 @@ fn link_as_relocatable_object() {
output: out2.clone(),
format: FormatOption::Static,
target: TARGET.map(String::from),
optimization: rusty::OptimizationLevel::Default,
},
None,
&triple,
Expand All @@ -232,6 +239,7 @@ fn link_as_relocatable_object() {
output: out1.clone(),
format: FormatOption::Relocatable,
target: TARGET.map(String::from),
optimization: rusty::OptimizationLevel::Default,
},
None,
&triple,
Expand Down Expand Up @@ -271,6 +279,7 @@ fn link_missing_file() {
output: out.clone(),
format: FormatOption::Static,
target: TARGET.map(String::from),
optimization: rusty::OptimizationLevel::Default,
},
None,
&triple,
Expand Down