mirror of
https://github.com/edg-l/edlang.git
synced 2024-11-22 07:58:24 +00:00
feat: usable edb
This commit is contained in:
parent
22498719e1
commit
bd3c4da7ea
8
Cargo.lock
generated
8
Cargo.lock
generated
|
@ -241,6 +241,7 @@ dependencies = [
|
||||||
"clap",
|
"clap",
|
||||||
"edlang_driver",
|
"edlang_driver",
|
||||||
"git2",
|
"git2",
|
||||||
|
"owo-colors",
|
||||||
"serde",
|
"serde",
|
||||||
"toml",
|
"toml",
|
||||||
]
|
]
|
||||||
|
@ -294,6 +295,7 @@ dependencies = [
|
||||||
"test-case",
|
"test-case",
|
||||||
"tracing",
|
"tracing",
|
||||||
"tracing-subscriber",
|
"tracing-subscriber",
|
||||||
|
"walkdir",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -785,6 +787,12 @@ version = "0.1.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
|
checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "owo-colors"
|
||||||
|
version = "4.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "caff54706df99d2a78a5a4e3455ff45448d81ef1bb63c22cd14052ca0e993a3f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "parking_lot"
|
name = "parking_lot"
|
||||||
version = "0.12.1"
|
version = "0.12.1"
|
||||||
|
|
|
@ -20,3 +20,4 @@ clap = { version = "4.4.16", features = ["derive"] }
|
||||||
toml = "0.8.10"
|
toml = "0.8.10"
|
||||||
serde = { version = "1.0.197", features = ["derive"] }
|
serde = { version = "1.0.197", features = ["derive"] }
|
||||||
git2 = "0.18.2"
|
git2 = "0.18.2"
|
||||||
|
owo-colors = "4.0.0"
|
||||||
|
|
154
edb/src/main.rs
154
edb/src/main.rs
|
@ -1,9 +1,15 @@
|
||||||
use std::{collections::HashMap, path::PathBuf};
|
use std::{collections::HashMap, fs::File, io::Read, path::PathBuf, time::Instant};
|
||||||
|
|
||||||
use anyhow::{Context, Result};
|
use anyhow::{bail, Context, Result};
|
||||||
use clap::{Parser, Subcommand};
|
use clap::{Parser, Subcommand};
|
||||||
use config::{Config, Package, Profile};
|
use config::{Config, Package, Profile};
|
||||||
use git2::{IndexAddOption, Repository, RepositoryInitOptions};
|
use edlang_driver::{
|
||||||
|
compile,
|
||||||
|
linker::{link_binary, link_shared_lib},
|
||||||
|
CompilerArgs,
|
||||||
|
};
|
||||||
|
use git2::{IndexAddOption, Repository};
|
||||||
|
use owo_colors::OwoColorize;
|
||||||
|
|
||||||
mod config;
|
mod config;
|
||||||
|
|
||||||
|
@ -36,6 +42,10 @@ enum Commands {
|
||||||
/// Build for release with all optimizations.
|
/// Build for release with all optimizations.
|
||||||
#[arg(short, long, default_value_t = false)]
|
#[arg(short, long, default_value_t = false)]
|
||||||
release: bool,
|
release: bool,
|
||||||
|
|
||||||
|
/// Override the profile to use.
|
||||||
|
#[arg(short, long)]
|
||||||
|
profile: Option<String>,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -131,13 +141,13 @@ mod {} {{
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut repo = Repository::init(&path).context("failed to create repository")?;
|
let repo = Repository::init(&path).context("failed to create repository")?;
|
||||||
let sig = repo.signature()?;
|
let sig = repo.signature()?;
|
||||||
let tree_id = {
|
let tree_id = {
|
||||||
let mut index = repo.index()?;
|
let mut index = repo.index()?;
|
||||||
|
|
||||||
index.add_all(["*"], IndexAddOption::DEFAULT, None)?;
|
index.add_all(["."].iter(), IndexAddOption::DEFAULT, None)?;
|
||||||
|
index.write()?;
|
||||||
index.write_tree()?
|
index.write_tree()?
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -145,8 +155,138 @@ mod {} {{
|
||||||
repo.commit(Some("HEAD"), &sig, &sig, "Initial commit", &tree, &[])
|
repo.commit(Some("HEAD"), &sig, &sig, "Initial commit", &tree, &[])
|
||||||
.context("failed to create initial commit")?;
|
.context("failed to create initial commit")?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if bin {
|
||||||
|
println!(
|
||||||
|
" {} binary (application) `{}` package",
|
||||||
|
"Created".green().bold(),
|
||||||
|
name
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
println!(" {} library `{}` package", "Created".green(), name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Commands::Build { release, profile } => {
|
||||||
|
let mut current_dir = std::env::current_dir()?;
|
||||||
|
let mut config_path = None;
|
||||||
|
|
||||||
|
for _ in 0..3 {
|
||||||
|
if !current_dir.join("Ed.toml").exists() {
|
||||||
|
current_dir = if let Some(parent) = current_dir.parent() {
|
||||||
|
parent.to_path_buf()
|
||||||
|
} else {
|
||||||
|
bail!("Couldn't find Ed.toml");
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
config_path = Some(current_dir.join("Ed.toml"));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let config_path = match config_path {
|
||||||
|
Some(x) => x,
|
||||||
|
None => bail!("Couldn't find Ed.toml"),
|
||||||
|
};
|
||||||
|
|
||||||
|
let base_dir = config_path
|
||||||
|
.parent()
|
||||||
|
.context("couldn't get config parent dir")?;
|
||||||
|
let mut config = File::open(&config_path).context("Failed to open Ed.toml")?;
|
||||||
|
let mut buf = String::new();
|
||||||
|
config.read_to_string(&mut buf)?;
|
||||||
|
|
||||||
|
let config: Config = toml::from_str(&buf).context("failed to parse Ed.toml")?;
|
||||||
|
|
||||||
|
println!(
|
||||||
|
" {} {} v{} ({})",
|
||||||
|
"Compiling".green().bold(),
|
||||||
|
config.package.name,
|
||||||
|
config.package.version,
|
||||||
|
base_dir.display()
|
||||||
|
);
|
||||||
|
|
||||||
|
let src_dir = base_dir.join("src");
|
||||||
|
let target_dir = base_dir.join("target-ed");
|
||||||
|
|
||||||
|
if !target_dir.exists() {
|
||||||
|
std::fs::create_dir_all(&target_dir)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
let has_main = src_dir.join("main.ed").exists();
|
||||||
|
let output = target_dir.join(config.package.name);
|
||||||
|
|
||||||
|
let (profile, profile_name) = if let Some(profile) = profile {
|
||||||
|
(
|
||||||
|
config
|
||||||
|
.profile
|
||||||
|
.get(&profile)
|
||||||
|
.context("Couldn't get requested profile")?,
|
||||||
|
profile,
|
||||||
|
)
|
||||||
|
} else if release {
|
||||||
|
(
|
||||||
|
config
|
||||||
|
.profile
|
||||||
|
.get("release")
|
||||||
|
.context("Couldn't get profile: release")?,
|
||||||
|
"release".to_string(),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
(
|
||||||
|
config
|
||||||
|
.profile
|
||||||
|
.get("dev")
|
||||||
|
.context("Couldn't get profile: dev")?,
|
||||||
|
"dev".to_string(),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
let compile_args = CompilerArgs {
|
||||||
|
input: src_dir,
|
||||||
|
output: output.clone(),
|
||||||
|
release,
|
||||||
|
optlevel: Some(profile.opt_level),
|
||||||
|
debug_info: Some(profile.debug_info),
|
||||||
|
library: !has_main,
|
||||||
|
ast: false,
|
||||||
|
ir: false,
|
||||||
|
llvm: true,
|
||||||
|
asm: false,
|
||||||
|
object: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
let start = Instant::now();
|
||||||
|
let object = compile(&compile_args)?;
|
||||||
|
|
||||||
|
if has_main {
|
||||||
|
link_shared_lib(&[object], &output)?;
|
||||||
|
} else {
|
||||||
|
link_binary(&[object], &output)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
let elapsed = start.elapsed();
|
||||||
|
|
||||||
|
println!(
|
||||||
|
" {} {} [{}{}] in {elapsed:?}",
|
||||||
|
"Finished".green().bold(),
|
||||||
|
profile_name,
|
||||||
|
if profile.opt_level > 0 {
|
||||||
|
"optimized"
|
||||||
|
} else {
|
||||||
|
"unoptimized"
|
||||||
|
},
|
||||||
|
if profile.debug_info {
|
||||||
|
" + debuginfo"
|
||||||
|
} else {
|
||||||
|
""
|
||||||
|
}
|
||||||
|
);
|
||||||
|
/*
|
||||||
|
|
||||||
|
Finished dev [unoptimized + debuginfo] target(s) in 0.06s
|
||||||
|
Running `/data2/edgar/edlang/target/debug/edb build`
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
Commands::Build { release } => todo!(),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -9,11 +9,15 @@ pub fn lowering_error_to_report(
|
||||||
error: LoweringError,
|
error: LoweringError,
|
||||||
session: &Session,
|
session: &Session,
|
||||||
) -> Report<(String, Range<usize>)> {
|
) -> Report<(String, Range<usize>)> {
|
||||||
let path = session.file_path.display().to_string();
|
|
||||||
let mut colors = ColorGenerator::new();
|
let mut colors = ColorGenerator::new();
|
||||||
colors.next();
|
colors.next();
|
||||||
match error {
|
match error {
|
||||||
LoweringError::ModuleNotFound { span, module } => {
|
LoweringError::ModuleNotFound {
|
||||||
|
span,
|
||||||
|
module,
|
||||||
|
file_id,
|
||||||
|
} => {
|
||||||
|
let path = session.file_paths[file_id].display().to_string();
|
||||||
let offset = span.lo;
|
let offset = span.lo;
|
||||||
Report::build(ReportKind::Error, path.clone(), offset)
|
Report::build(ReportKind::Error, path.clone(), offset)
|
||||||
.with_code("E1")
|
.with_code("E1")
|
||||||
|
@ -25,55 +29,79 @@ pub fn lowering_error_to_report(
|
||||||
.with_message("Unresolved import.")
|
.with_message("Unresolved import.")
|
||||||
.finish()
|
.finish()
|
||||||
}
|
}
|
||||||
LoweringError::FunctionNotFound { span, function } => {
|
LoweringError::FunctionNotFound {
|
||||||
|
span,
|
||||||
|
function,
|
||||||
|
file_id,
|
||||||
|
} => {
|
||||||
|
let path = session.file_paths[file_id].display().to_string();
|
||||||
Report::build(ReportKind::Error, path.clone(), span.lo)
|
Report::build(ReportKind::Error, path.clone(), span.lo)
|
||||||
.with_code("EFNNOTFOUND")
|
.with_code("EFNNOTFOUND")
|
||||||
.with_label(
|
.with_label(
|
||||||
Label::new((path, span.into()))
|
Label::new((path, span.into()))
|
||||||
.with_message(format!("Function {function:?} not found."))
|
.with_message(format!("Function {function:?} not found."))
|
||||||
.with_color(colors.next()),
|
.with_color(colors.next()),
|
||||||
)
|
)
|
||||||
.finish()
|
.finish()
|
||||||
},
|
}
|
||||||
LoweringError::ImportNotFound { import_span, module_span, symbol } => {
|
LoweringError::ImportNotFound {
|
||||||
let offset = symbol.span.lo;
|
import_span,
|
||||||
Report::build(ReportKind::Error, path.clone(), offset)
|
module_span,
|
||||||
.with_code("E2")
|
symbol,
|
||||||
.with_label(
|
file_id,
|
||||||
Label::new((path.clone(), module_span.into()))
|
} => {
|
||||||
.with_message("In module this module."),
|
let path = session.file_paths[file_id].display().to_string();
|
||||||
)
|
let offset = symbol.span.lo;
|
||||||
.with_label(
|
Report::build(ReportKind::Error, path.clone(), offset)
|
||||||
Label::new((path.clone(), import_span.into()))
|
.with_code("E2")
|
||||||
.with_message("In this import statement"),
|
.with_label(
|
||||||
)
|
Label::new((path.clone(), module_span.into()))
|
||||||
.with_label(
|
.with_message("In module this module."),
|
||||||
Label::new((path, symbol.span.into()))
|
)
|
||||||
.with_message(format!("Failed to find symbol {:?}", symbol.name))
|
.with_label(
|
||||||
.with_color(colors.next()),
|
Label::new((path.clone(), import_span.into()))
|
||||||
)
|
.with_message("In this import statement"),
|
||||||
.with_message("Unresolved import.")
|
)
|
||||||
.finish()
|
.with_label(
|
||||||
},
|
Label::new((path, symbol.span.into()))
|
||||||
LoweringError::BorrowNotMutable { span, name, type_span } => {
|
.with_message(format!("Failed to find symbol {:?}", symbol.name))
|
||||||
let mut labels = vec![
|
.with_color(colors.next()),
|
||||||
Label::new((path.clone(), span.into()))
|
)
|
||||||
.with_message(format!("Can't mutate {name:?} because it's behind a immutable borrow"))
|
.with_message("Unresolved import.")
|
||||||
.with_color(colors.next())
|
.finish()
|
||||||
];
|
}
|
||||||
|
LoweringError::BorrowNotMutable {
|
||||||
|
span,
|
||||||
|
name,
|
||||||
|
type_span,
|
||||||
|
file_id,
|
||||||
|
} => {
|
||||||
|
let path = session.file_paths[file_id].display().to_string();
|
||||||
|
let mut labels = vec![Label::new((path.clone(), span.into()))
|
||||||
|
.with_message(format!(
|
||||||
|
"Can't mutate {name:?} because it's behind a immutable borrow"
|
||||||
|
))
|
||||||
|
.with_color(colors.next())];
|
||||||
|
|
||||||
if let Some(type_span) = type_span {
|
if let Some(type_span) = type_span {
|
||||||
labels.push(Label::new((path.clone(), type_span.into()))
|
labels.push(
|
||||||
.with_message(format!("Variable {name:?} has this type"))
|
Label::new((path.clone(), type_span.into()))
|
||||||
.with_color(colors.next()));
|
.with_message(format!("Variable {name:?} has this type"))
|
||||||
|
.with_color(colors.next()),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Report::build(ReportKind::Error, path.clone(), span.lo)
|
Report::build(ReportKind::Error, path.clone(), span.lo)
|
||||||
.with_code("EREFMUT")
|
.with_code("EREFMUT")
|
||||||
.with_labels(labels)
|
.with_labels(labels)
|
||||||
.finish()
|
.finish()
|
||||||
},
|
}
|
||||||
LoweringError::UnrecognizedType { span, name } => {
|
LoweringError::UnrecognizedType {
|
||||||
|
span,
|
||||||
|
name,
|
||||||
|
file_id,
|
||||||
|
} => {
|
||||||
|
let path = session.file_paths[file_id].display().to_string();
|
||||||
Report::build(ReportKind::Error, path.clone(), span.lo)
|
Report::build(ReportKind::Error, path.clone(), span.lo)
|
||||||
.with_code("E3")
|
.with_code("E3")
|
||||||
.with_label(
|
.with_label(
|
||||||
|
@ -83,19 +111,26 @@ pub fn lowering_error_to_report(
|
||||||
)
|
)
|
||||||
.with_message(format!("Unresolved type {:?}.", name))
|
.with_message(format!("Unresolved type {:?}.", name))
|
||||||
.finish()
|
.finish()
|
||||||
},
|
}
|
||||||
LoweringError::UnexpectedType { span, found, expected } => {
|
LoweringError::UnexpectedType {
|
||||||
let mut labels = vec![
|
span,
|
||||||
Label::new((path.clone(), span.into()))
|
found,
|
||||||
.with_message(format!("Unexpected type '{}', expected '{}'", found, expected.kind))
|
expected,
|
||||||
.with_color(colors.next())
|
file_id,
|
||||||
];
|
} => {
|
||||||
|
let path = session.file_paths[file_id].display().to_string();
|
||||||
|
let mut labels = vec![Label::new((path.clone(), span.into()))
|
||||||
|
.with_message(format!(
|
||||||
|
"Unexpected type '{}', expected '{}'",
|
||||||
|
found, expected.kind
|
||||||
|
))
|
||||||
|
.with_color(colors.next())];
|
||||||
|
|
||||||
if let Some(span) = expected.span {
|
if let Some(span) = expected.span {
|
||||||
labels.push(
|
labels.push(
|
||||||
Label::new((path.clone(), span.into()))
|
Label::new((path.clone(), span.into()))
|
||||||
.with_message(format!("expected '{}' due to this type", expected.kind))
|
.with_message(format!("expected '{}' due to this type", expected.kind))
|
||||||
.with_color(colors.next())
|
.with_color(colors.next()),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,8 +139,9 @@ pub fn lowering_error_to_report(
|
||||||
.with_labels(labels)
|
.with_labels(labels)
|
||||||
.with_message(format!("expected type {}.", expected.kind))
|
.with_message(format!("expected type {}.", expected.kind))
|
||||||
.finish()
|
.finish()
|
||||||
},
|
}
|
||||||
LoweringError::IdNotFound { span, id } => {
|
LoweringError::IdNotFound { span, id, file_id } => {
|
||||||
|
let path = session.file_paths[file_id].display().to_string();
|
||||||
Report::build(ReportKind::Error, path.clone(), span.lo)
|
Report::build(ReportKind::Error, path.clone(), span.lo)
|
||||||
.with_code("E_ID")
|
.with_code("E_ID")
|
||||||
.with_label(
|
.with_label(
|
||||||
|
@ -115,8 +151,13 @@ pub fn lowering_error_to_report(
|
||||||
)
|
)
|
||||||
.with_message(format!("Failed to find definition id {id:?}, this is most likely a compiler bug or a unimplemented lowering"))
|
.with_message(format!("Failed to find definition id {id:?}, this is most likely a compiler bug or a unimplemented lowering"))
|
||||||
.finish()
|
.finish()
|
||||||
},
|
}
|
||||||
LoweringError::NotYetImplemented { span, message } => {
|
LoweringError::NotYetImplemented {
|
||||||
|
span,
|
||||||
|
message,
|
||||||
|
file_id,
|
||||||
|
} => {
|
||||||
|
let path = session.file_paths[file_id].display().to_string();
|
||||||
Report::build(ReportKind::Error, path.clone(), span.lo)
|
Report::build(ReportKind::Error, path.clone(), span.lo)
|
||||||
.with_code("TODO")
|
.with_code("TODO")
|
||||||
.with_label(
|
.with_label(
|
||||||
|
@ -125,16 +166,21 @@ pub fn lowering_error_to_report(
|
||||||
.with_color(colors.next()),
|
.with_color(colors.next()),
|
||||||
)
|
)
|
||||||
.finish()
|
.finish()
|
||||||
},
|
}
|
||||||
LoweringError::UseOfUndeclaredVariable { span, name } => {
|
LoweringError::UseOfUndeclaredVariable {
|
||||||
|
span,
|
||||||
|
name,
|
||||||
|
file_id,
|
||||||
|
} => {
|
||||||
|
let path = session.file_paths[file_id].display().to_string();
|
||||||
Report::build(ReportKind::Error, path.clone(), span.lo)
|
Report::build(ReportKind::Error, path.clone(), span.lo)
|
||||||
.with_code("UseOfUndeclaredVariable")
|
.with_code("UseOfUndeclaredVariable")
|
||||||
.with_label(
|
.with_label(
|
||||||
Label::new((path, span.into()))
|
Label::new((path, span.into()))
|
||||||
.with_message(format!("use of undeclared variable {:?}", name))
|
.with_message(format!("use of undeclared variable {:?}", name))
|
||||||
.with_color(colors.next()),
|
.with_color(colors.next()),
|
||||||
)
|
)
|
||||||
.finish()
|
.finish()
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,17 +35,19 @@ struct ModuleCompileCtx<'ctx, 'm> {
|
||||||
di_builder: DebugInfoBuilder<'ctx>,
|
di_builder: DebugInfoBuilder<'ctx>,
|
||||||
di_unit: DICompileUnit<'ctx>,
|
di_unit: DICompileUnit<'ctx>,
|
||||||
target_data: TargetData,
|
target_data: TargetData,
|
||||||
_module_id: DefId,
|
module_id: DefId,
|
||||||
di_namespace: DIScope<'ctx>,
|
di_namespace: DIScope<'ctx>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'ctx, 'm> ModuleCompileCtx<'ctx, 'm> {
|
impl<'ctx, 'm> ModuleCompileCtx<'ctx, 'm> {
|
||||||
pub fn _get_module_body(&self) -> &ModuleBody {
|
pub fn get_module_body(&self) -> &ModuleBody {
|
||||||
self.ctx.program.modules.get(&self._module_id).unwrap()
|
self.ctx.program.modules.get(&self.module_id).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_debug_loc(&self, scope: DIScope<'ctx>, span: Span) -> DILocation<'ctx> {
|
pub fn set_debug_loc(&self, scope: DIScope<'ctx>, span: Span) -> DILocation<'ctx> {
|
||||||
let (_, line, column) = self.ctx.session.source.get_offset_line(span.lo).unwrap();
|
let (_, line, column) = self.ctx.session.sources[self.get_module_body().file_id]
|
||||||
|
.get_offset_line(span.lo)
|
||||||
|
.unwrap();
|
||||||
let debug_loc = self.di_builder.create_debug_location(
|
let debug_loc = self.di_builder.create_debug_location(
|
||||||
self.ctx.context,
|
self.ctx.context,
|
||||||
line as u32 + 1,
|
line as u32 + 1,
|
||||||
|
@ -98,25 +100,39 @@ pub fn compile(session: &Session, program: &ProgramBody) -> Result<PathBuf, Box<
|
||||||
|
|
||||||
info!("compiling for: {:?}", target.get_description());
|
info!("compiling for: {:?}", target.get_description());
|
||||||
|
|
||||||
let filename = session.file_path.file_name().unwrap().to_string_lossy();
|
|
||||||
let dir = session.file_path.parent().unwrap().to_string_lossy();
|
|
||||||
for module_id in program.top_level_modules.iter() {
|
for module_id in program.top_level_modules.iter() {
|
||||||
let module = ctx.program.modules.get(module_id).unwrap();
|
let module = ctx.program.modules.get(module_id).unwrap();
|
||||||
|
let file_path = session.file_paths[module.file_id].clone();
|
||||||
|
let abs_file_path = file_path
|
||||||
|
.canonicalize()
|
||||||
|
.expect("failed to canonicalize file path");
|
||||||
|
let filename = file_path.file_name().unwrap().to_str().unwrap();
|
||||||
|
let dirname = abs_file_path
|
||||||
|
.parent()
|
||||||
|
.unwrap()
|
||||||
|
.file_name()
|
||||||
|
.unwrap()
|
||||||
|
.to_str()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
let llvm_module = context.create_module(&module.name);
|
let llvm_module = context.create_module(&module.name);
|
||||||
llvm_module.set_source_file_name(&filename);
|
llvm_module.set_source_file_name(filename);
|
||||||
llvm_module.set_triple(&triple);
|
llvm_module.set_triple(&triple);
|
||||||
llvm_module.set_data_layout(&machine.get_target_data().get_data_layout());
|
llvm_module.set_data_layout(&machine.get_target_data().get_data_layout());
|
||||||
let (di_builder, di_unit) = llvm_module.create_debug_info_builder(
|
let (di_builder, di_unit) = llvm_module.create_debug_info_builder(
|
||||||
true,
|
true,
|
||||||
inkwell::debug_info::DWARFSourceLanguage::Rust,
|
inkwell::debug_info::DWARFSourceLanguage::Rust,
|
||||||
&filename,
|
filename,
|
||||||
&dir,
|
dirname,
|
||||||
"edlang",
|
"edlang",
|
||||||
true,
|
true,
|
||||||
"", // compiler flags
|
"", // compiler flags
|
||||||
1,
|
1,
|
||||||
"", // split name
|
"", // split name
|
||||||
inkwell::debug_info::DWARFEmissionKind::Full,
|
match session.debug_info {
|
||||||
|
edlang_session::DebugInfo::None => inkwell::debug_info::DWARFEmissionKind::None,
|
||||||
|
edlang_session::DebugInfo::Full => inkwell::debug_info::DWARFEmissionKind::Full,
|
||||||
|
},
|
||||||
module.module_id.program_id.try_into().unwrap(), // compile unit id?
|
module.module_id.program_id.try_into().unwrap(), // compile unit id?
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
|
@ -135,7 +151,7 @@ pub fn compile(session: &Session, program: &ProgramBody) -> Result<PathBuf, Box<
|
||||||
di_unit,
|
di_unit,
|
||||||
builder: &builder,
|
builder: &builder,
|
||||||
target_data: machine.get_target_data(),
|
target_data: machine.get_target_data(),
|
||||||
_module_id: *module_id,
|
module_id: *module_id,
|
||||||
di_namespace,
|
di_namespace,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -234,10 +250,7 @@ fn compile_fn_signature(ctx: &ModuleCompileCtx<'_, '_>, fn_id: DefId) {
|
||||||
|
|
||||||
fn_value.set_call_conventions(0); // cconv
|
fn_value.set_call_conventions(0); // cconv
|
||||||
|
|
||||||
let (_, line, _col) = ctx
|
let (_, line, _col) = ctx.ctx.session.sources[ctx.get_module_body().file_id]
|
||||||
.ctx
|
|
||||||
.session
|
|
||||||
.source
|
|
||||||
.get_offset_line(body.fn_span.lo)
|
.get_offset_line(body.fn_span.lo)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
@ -1480,10 +1493,7 @@ fn compile_debug_type<'ctx>(ctx: &ModuleCompileCtx<'ctx, '_>, ty: &ir::TypeInfo)
|
||||||
fields.push(ty);
|
fields.push(ty);
|
||||||
}
|
}
|
||||||
|
|
||||||
let (_, line, _column) = ctx
|
let (_, line, _column) = ctx.ctx.session.sources[ctx.get_module_body().file_id]
|
||||||
.ctx
|
|
||||||
.session
|
|
||||||
.source
|
|
||||||
.get_offset_line(body.span.lo)
|
.get_offset_line(body.span.lo)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let real_ty = compile_basic_type(ctx, ty);
|
let real_ty = compile_basic_type(ctx, ty);
|
||||||
|
|
|
@ -7,7 +7,6 @@ use edlang_session::Session;
|
||||||
use ir::ProgramBody;
|
use ir::ProgramBody;
|
||||||
|
|
||||||
pub mod codegen;
|
pub mod codegen;
|
||||||
pub mod linker;
|
|
||||||
|
|
||||||
pub fn compile(
|
pub fn compile(
|
||||||
session: &Session,
|
session: &Session,
|
||||||
|
|
|
@ -25,6 +25,7 @@ edlang_parser = { version = "0.0.1-alpha.12", path = "../edlang_parser" }
|
||||||
edlang_session = { version = "0.0.1-alpha.12", path = "../edlang_session" }
|
edlang_session = { version = "0.0.1-alpha.12", path = "../edlang_session" }
|
||||||
tracing = { workspace = true }
|
tracing = { workspace = true }
|
||||||
tracing-subscriber = { version = "0.3.18", features = ["env-filter"] }
|
tracing-subscriber = { version = "0.3.18", features = ["env-filter"] }
|
||||||
|
walkdir = "2.5.0"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
tempfile = "3.10.1"
|
tempfile = "3.10.1"
|
||||||
|
|
|
@ -1,49 +1,60 @@
|
||||||
use std::{path::PathBuf, time::Instant};
|
use std::{path::PathBuf, time::Instant};
|
||||||
|
|
||||||
use anyhow::{bail, Result};
|
use anyhow::Result;
|
||||||
use ariadne::Source;
|
use ariadne::{sources, Source};
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use edlang_codegen_llvm::linker::{link_binary, link_shared_lib};
|
|
||||||
use edlang_lowering::lower_modules;
|
use edlang_lowering::lower_modules;
|
||||||
use edlang_session::{DebugInfo, OptLevel, Session};
|
use edlang_session::{DebugInfo, OptLevel, Session};
|
||||||
|
use walkdir::WalkDir;
|
||||||
|
|
||||||
|
use crate::linker::{link_binary, link_shared_lib};
|
||||||
|
|
||||||
|
pub mod linker;
|
||||||
|
|
||||||
#[derive(Parser, Debug)]
|
#[derive(Parser, Debug)]
|
||||||
#[command(author, version, about = "edlang compiler driver", long_about = None, bin_name = "edlangc")]
|
#[command(author, version, about = "edlang compiler driver", long_about = None, bin_name = "edlangc")]
|
||||||
pub struct CompilerArgs {
|
pub struct CompilerArgs {
|
||||||
/// The input file.
|
/// The input file.
|
||||||
input: PathBuf,
|
pub input: PathBuf,
|
||||||
|
|
||||||
|
/// The output file.
|
||||||
|
pub output: PathBuf,
|
||||||
|
|
||||||
/// Build for release with all optimizations.
|
/// Build for release with all optimizations.
|
||||||
#[arg(short, long, default_value_t = false)]
|
#[arg(short, long, default_value_t = false)]
|
||||||
release: bool,
|
pub release: bool,
|
||||||
|
|
||||||
/// Set the optimization level, 0,1,2,3
|
/// Set the optimization level, 0,1,2,3
|
||||||
#[arg(short = 'O', long)]
|
#[arg(short = 'O', long)]
|
||||||
optlevel: Option<u8>,
|
pub optlevel: Option<u8>,
|
||||||
|
|
||||||
/// Always add debug info
|
/// Always add debug info
|
||||||
#[arg(long)]
|
#[arg(long)]
|
||||||
debug_info: Option<bool>,
|
pub debug_info: Option<bool>,
|
||||||
|
|
||||||
/// Build as a library.
|
/// Build as a library.
|
||||||
#[arg(short, long, default_value_t = false)]
|
#[arg(short, long, default_value_t = false)]
|
||||||
library: bool,
|
pub library: bool,
|
||||||
|
|
||||||
/// Print the edlang AST
|
/// Print the edlang AST
|
||||||
#[arg(long, default_value_t = false)]
|
#[arg(long, default_value_t = false)]
|
||||||
ast: bool,
|
pub ast: bool,
|
||||||
|
|
||||||
/// Print the edlang IR
|
/// Print the edlang IR
|
||||||
#[arg(long, default_value_t = false)]
|
#[arg(long, default_value_t = false)]
|
||||||
ir: bool,
|
pub ir: bool,
|
||||||
|
|
||||||
/// Output llvm ir
|
/// Output llvm ir
|
||||||
#[arg(long, default_value_t = false)]
|
#[arg(long, default_value_t = false)]
|
||||||
llvm: bool,
|
pub llvm: bool,
|
||||||
|
|
||||||
/// Output asm
|
/// Output asm
|
||||||
#[arg(long, default_value_t = false)]
|
#[arg(long, default_value_t = false)]
|
||||||
asm: bool,
|
pub asm: bool,
|
||||||
|
|
||||||
|
/// Output a object file
|
||||||
|
#[arg(long, default_value_t = false)]
|
||||||
|
pub object: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn main() -> Result<()> {
|
pub fn main() -> Result<()> {
|
||||||
|
@ -51,51 +62,59 @@ pub fn main() -> Result<()> {
|
||||||
|
|
||||||
let args = CompilerArgs::parse();
|
let args = CompilerArgs::parse();
|
||||||
|
|
||||||
compile_single_file(args)?;
|
let object = compile(&args)?;
|
||||||
|
|
||||||
|
if args.library {
|
||||||
|
link_shared_lib(&[object.clone()], &args.output)?;
|
||||||
|
} else {
|
||||||
|
link_binary(&[object.clone()], &args.output)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if !args.object {
|
||||||
|
std::fs::remove_file(object)?;
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn compile_single_file(args: CompilerArgs) -> Result<()> {
|
pub fn compile(args: &CompilerArgs) -> Result<PathBuf> {
|
||||||
if !args.input.is_file() {
|
let mut files = Vec::new();
|
||||||
bail!("Input is not a file");
|
for entry in WalkDir::new(&args.input) {
|
||||||
|
let entry = entry?;
|
||||||
|
if let Some(ext) = entry.path().extension() {
|
||||||
|
if ext.eq_ignore_ascii_case("ed") {
|
||||||
|
files.push(entry.path().to_path_buf());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if files.is_empty() {
|
||||||
|
panic!("files is empty");
|
||||||
}
|
}
|
||||||
|
|
||||||
let start_time = Instant::now();
|
let start_time = Instant::now();
|
||||||
|
|
||||||
tracing_subscriber::fmt::init();
|
let mut modules = Vec::new();
|
||||||
|
|
||||||
let path = args.input.display().to_string();
|
for path in files {
|
||||||
let source = std::fs::read_to_string(&args.input)?;
|
let source = std::fs::read_to_string(&path)?;
|
||||||
|
|
||||||
let modules = edlang_parser::parse_ast(&source);
|
let modules_ast = edlang_parser::parse_ast(&source);
|
||||||
|
|
||||||
let modules = match modules {
|
let modules_temp = match modules_ast {
|
||||||
Ok(modules) => modules,
|
Ok(modules) => modules,
|
||||||
Err(error) => {
|
Err(error) => {
|
||||||
let report = edlang_parser::error_to_report(&path, &error)?;
|
let path = path.display().to_string();
|
||||||
edlang_parser::print_report(&path, &source, report)?;
|
let report = edlang_parser::error_to_report(&path, &error)?;
|
||||||
std::process::exit(1)
|
edlang_parser::print_report(&path, &source, report)?;
|
||||||
}
|
std::process::exit(1)
|
||||||
};
|
}
|
||||||
|
};
|
||||||
let cwd = std::env::current_dir()?;
|
modules.push((path, source, modules_temp));
|
||||||
// todo: find a better name, "target" would clash with rust if running in the source tree.
|
|
||||||
let target_dir = cwd.join("target_ed/");
|
|
||||||
if !target_dir.exists() {
|
|
||||||
std::fs::create_dir_all(&target_dir)?;
|
|
||||||
}
|
}
|
||||||
let output_file = target_dir.join(PathBuf::from(args.input.file_name().unwrap()));
|
|
||||||
let output_file = if args.library {
|
|
||||||
output_file.with_extension(Session::get_platform_library_ext())
|
|
||||||
} else if cfg!(target_os = "windows") {
|
|
||||||
output_file.with_extension("exe")
|
|
||||||
} else {
|
|
||||||
output_file.with_extension("")
|
|
||||||
};
|
|
||||||
|
|
||||||
let session = Session {
|
let session = Session {
|
||||||
file_path: args.input,
|
file_paths: modules.iter().map(|x| x.0.clone()).collect(),
|
||||||
debug_info: if let Some(debug_info) = args.debug_info {
|
debug_info: if let Some(debug_info) = args.debug_info {
|
||||||
if debug_info {
|
if debug_info {
|
||||||
DebugInfo::Full
|
DebugInfo::Full
|
||||||
|
@ -119,50 +138,50 @@ pub fn compile_single_file(args: CompilerArgs) -> Result<()> {
|
||||||
} else {
|
} else {
|
||||||
OptLevel::None
|
OptLevel::None
|
||||||
},
|
},
|
||||||
source: Source::from(source),
|
sources: modules.iter().map(|x| Source::from(x.1.clone())).collect(),
|
||||||
library: args.library,
|
library: args.library,
|
||||||
target_dir,
|
output_file: args.output.with_extension("o"),
|
||||||
output_file,
|
|
||||||
output_asm: args.asm,
|
output_asm: args.asm,
|
||||||
output_llvm: args.llvm,
|
output_llvm: args.llvm,
|
||||||
};
|
};
|
||||||
tracing::debug!("Input file: {:#?}", session.file_path);
|
|
||||||
tracing::debug!("Target dir: {:#?}", session.target_dir);
|
|
||||||
tracing::debug!("Output file: {:#?}", session.output_file);
|
tracing::debug!("Output file: {:#?}", session.output_file);
|
||||||
tracing::debug!("Is library: {:#?}", session.library);
|
tracing::debug!("Is library: {:#?}", session.library);
|
||||||
tracing::debug!("Optlevel: {:#?}", session.optlevel);
|
tracing::debug!("Optlevel: {:#?}", session.optlevel);
|
||||||
tracing::debug!("Debug Info: {:#?}", session.debug_info);
|
tracing::debug!("Debug Info: {:#?}", session.debug_info);
|
||||||
|
|
||||||
|
let path_cache: Vec<_> = modules
|
||||||
|
.iter()
|
||||||
|
.map(|x| (x.0.display().to_string(), x.1.clone()))
|
||||||
|
.collect();
|
||||||
|
let modules: Vec<_> = modules.iter().map(|x| x.2.clone()).collect();
|
||||||
|
|
||||||
if args.ast {
|
if args.ast {
|
||||||
println!("{:#?}", modules);
|
std::fs::write(
|
||||||
return Ok(());
|
session.output_file.with_extension("ast"),
|
||||||
|
format!("{:#?}", modules),
|
||||||
|
)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let program_ir = match lower_modules(&modules) {
|
let program_ir = match lower_modules(&modules) {
|
||||||
Ok(ir) => ir,
|
Ok(ir) => ir,
|
||||||
Err(error) => {
|
Err(error) => {
|
||||||
let report = edlang_check::lowering_error_to_report(error, &session);
|
let report = edlang_check::lowering_error_to_report(error, &session);
|
||||||
let path = session.file_path.display().to_string();
|
report.eprint(sources(path_cache))?;
|
||||||
report.eprint((path, session.source.clone()))?;
|
|
||||||
std::process::exit(1);
|
std::process::exit(1);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if args.ir {
|
if args.ir {
|
||||||
println!("{:#?}", program_ir);
|
std::fs::write(
|
||||||
return Ok(());
|
session.output_file.with_extension("ir"),
|
||||||
|
format!("{:#?}", program_ir),
|
||||||
|
)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let object_path = edlang_codegen_llvm::compile(&session, &program_ir).unwrap();
|
let object_path = edlang_codegen_llvm::compile(&session, &program_ir).unwrap();
|
||||||
|
|
||||||
if session.library {
|
|
||||||
link_shared_lib(&object_path, &session.output_file)?;
|
|
||||||
} else {
|
|
||||||
link_binary(&object_path, &session.output_file)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
let elapsed = start_time.elapsed();
|
let elapsed = start_time.elapsed();
|
||||||
tracing::debug!("Done in {:?}", elapsed);
|
tracing::debug!("Done in {:?}", elapsed);
|
||||||
|
|
||||||
Ok(())
|
Ok(object_path)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,39 +1,41 @@
|
||||||
use std::path::Path;
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
use tracing::instrument;
|
use tracing::instrument;
|
||||||
|
|
||||||
#[instrument(level = "debug")]
|
#[instrument(level = "debug")]
|
||||||
pub fn link_shared_lib(input_path: &Path, output_filename: &Path) -> std::io::Result<()> {
|
pub fn link_shared_lib(objects: &[PathBuf], output_filename: &Path) -> std::io::Result<()> {
|
||||||
let args: &[&str] = {
|
let objects: Vec<_> = objects.iter().map(|x| x.display().to_string()).collect();
|
||||||
|
let output_filename = output_filename.to_string_lossy().to_string();
|
||||||
|
|
||||||
|
let args: Vec<_> = {
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
{
|
{
|
||||||
&[
|
let mut args = vec![
|
||||||
"-demangle",
|
"-demangle",
|
||||||
"-no_deduplicate",
|
"-no_deduplicate",
|
||||||
"-dynamic",
|
"-dynamic",
|
||||||
"-dylib",
|
"-dylib",
|
||||||
"-L/usr/local/lib",
|
"-L/usr/local/lib",
|
||||||
"-L/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib",
|
"-L/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib",
|
||||||
&input_path.display().to_string(),
|
];
|
||||||
"-o",
|
|
||||||
&output_filename.display().to_string(),
|
args.extend(objects.iter().map(|x| x.as_str()));
|
||||||
"-lSystem",
|
|
||||||
]
|
args.extend(&["-o", &output_filename, "-lSystem"]);
|
||||||
|
|
||||||
|
args
|
||||||
}
|
}
|
||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
{
|
{
|
||||||
&[
|
let mut args = vec!["--hash-style=gnu", "--eh-frame-hdr", "-shared"];
|
||||||
"--hash-style=gnu",
|
|
||||||
"--eh-frame-hdr",
|
args.extend(&["-o", &output_filename]);
|
||||||
"-shared",
|
|
||||||
"-o",
|
args.extend(&["-L/lib/../lib64", "-L/usr/lib/../lib64", "-lc", "-O1"]);
|
||||||
&output_filename.display().to_string(),
|
|
||||||
"-L/lib/../lib64",
|
args.extend(objects.iter().map(|x| x.as_str()));
|
||||||
"-L/usr/lib/../lib64",
|
|
||||||
"-lc",
|
args
|
||||||
"-O1",
|
|
||||||
&input_path.display().to_string(),
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
{
|
{
|
||||||
|
@ -48,18 +50,24 @@ pub fn link_shared_lib(input_path: &Path, output_filename: &Path) -> std::io::Re
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(level = "debug")]
|
#[instrument(level = "debug")]
|
||||||
pub fn link_binary(input_path: &Path, output_filename: &Path) -> std::io::Result<()> {
|
pub fn link_binary(objects: &[PathBuf], output_filename: &Path) -> std::io::Result<()> {
|
||||||
let args: &[&str] = {
|
let objects: Vec<_> = objects.iter().map(|x| x.display().to_string()).collect();
|
||||||
|
let output_filename = output_filename.to_string_lossy().to_string();
|
||||||
|
|
||||||
|
let args: Vec<_> = {
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
{
|
{
|
||||||
&[
|
let mut args = vec![
|
||||||
"-L/usr/local/lib",
|
"-L/usr/local/lib",
|
||||||
"-L/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib",
|
"-L/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib",
|
||||||
&input_path.display().to_string(),
|
&input_path.display().to_string(),
|
||||||
"-o",
|
];
|
||||||
&output_filename.display().to_string(),
|
|
||||||
"-lSystem",
|
args.extend(objects.iter().map(|x| x.as_str()));
|
||||||
]
|
|
||||||
|
args.extend(&["-o", &output_filename, "-lSystem"]);
|
||||||
|
|
||||||
|
args
|
||||||
}
|
}
|
||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
{
|
{
|
||||||
|
@ -79,7 +87,7 @@ pub fn link_binary(input_path: &Path, output_filename: &Path) -> std::io::Result
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
&[
|
let mut args = vec![
|
||||||
"-pie",
|
"-pie",
|
||||||
"--hash-style=gnu",
|
"--hash-style=gnu",
|
||||||
"--eh-frame-hdr",
|
"--eh-frame-hdr",
|
||||||
|
@ -89,8 +97,11 @@ pub fn link_binary(input_path: &Path, output_filename: &Path) -> std::io::Result
|
||||||
"elf_x86_64",
|
"elf_x86_64",
|
||||||
scrt1,
|
scrt1,
|
||||||
crti,
|
crti,
|
||||||
"-o",
|
];
|
||||||
&output_filename.display().to_string(),
|
|
||||||
|
args.extend(&["-o", &output_filename]);
|
||||||
|
|
||||||
|
args.extend(&[
|
||||||
"-L/lib64",
|
"-L/lib64",
|
||||||
"-L/usr/lib64",
|
"-L/usr/lib64",
|
||||||
"-L/lib/x86_64-linux-gnu",
|
"-L/lib/x86_64-linux-gnu",
|
||||||
|
@ -99,8 +110,11 @@ pub fn link_binary(input_path: &Path, output_filename: &Path) -> std::io::Result
|
||||||
"-lc",
|
"-lc",
|
||||||
"-O1",
|
"-O1",
|
||||||
crtn,
|
crtn,
|
||||||
&input_path.display().to_string(),
|
]);
|
||||||
]
|
|
||||||
|
args.extend(objects.iter().map(|x| x.as_str()));
|
||||||
|
|
||||||
|
args
|
||||||
}
|
}
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
{
|
{
|
|
@ -6,7 +6,7 @@ use std::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use ariadne::Source;
|
use ariadne::Source;
|
||||||
use edlang_codegen_llvm::linker::{link_binary, link_shared_lib};
|
use edlang_driver::linker::{link_binary, link_shared_lib};
|
||||||
use edlang_lowering::lower_modules;
|
use edlang_lowering::lower_modules;
|
||||||
use edlang_session::{DebugInfo, OptLevel, Session};
|
use edlang_session::{DebugInfo, OptLevel, Session};
|
||||||
use tempfile::TempDir;
|
use tempfile::TempDir;
|
||||||
|
@ -36,13 +36,9 @@ pub fn compile_program(
|
||||||
) -> Result<CompileResult, Box<dyn std::error::Error>> {
|
) -> Result<CompileResult, Box<dyn std::error::Error>> {
|
||||||
let modules = edlang_parser::parse_ast(source).unwrap();
|
let modules = edlang_parser::parse_ast(source).unwrap();
|
||||||
|
|
||||||
let test_dir = tempfile::tempdir()?;
|
let test_dir = tempfile::tempdir().unwrap();
|
||||||
let test_dir_path = test_dir.path();
|
let test_dir_path = test_dir.path().canonicalize()?;
|
||||||
let target_dir = test_dir_path.join("build_artifacts/");
|
let output_file = test_dir_path.join(PathBuf::from(name));
|
||||||
if !target_dir.exists() {
|
|
||||||
std::fs::create_dir_all(&target_dir)?;
|
|
||||||
}
|
|
||||||
let output_file = target_dir.join(PathBuf::from(name));
|
|
||||||
let output_file = if library {
|
let output_file = if library {
|
||||||
output_file.with_extension(Session::get_platform_library_ext())
|
output_file.with_extension(Session::get_platform_library_ext())
|
||||||
} else if cfg!(target_os = "windows") {
|
} else if cfg!(target_os = "windows") {
|
||||||
|
@ -51,26 +47,28 @@ pub fn compile_program(
|
||||||
output_file.with_extension("")
|
output_file.with_extension("")
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let input_file = output_file.with_extension("ed");
|
||||||
|
std::fs::write(&input_file, source)?;
|
||||||
|
|
||||||
let session = Session {
|
let session = Session {
|
||||||
file_path: PathBuf::from(name),
|
file_paths: vec![input_file],
|
||||||
debug_info: DebugInfo::Full,
|
debug_info: DebugInfo::Full,
|
||||||
optlevel: OptLevel::Default,
|
optlevel: OptLevel::Default,
|
||||||
source: Source::from(source.to_string()),
|
sources: vec![Source::from(source.to_string())],
|
||||||
library,
|
library,
|
||||||
target_dir,
|
|
||||||
output_file,
|
output_file,
|
||||||
output_llvm: false,
|
output_llvm: false,
|
||||||
output_asm: false,
|
output_asm: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
let program_ir = lower_modules(&modules)?;
|
let program_ir = lower_modules(&[modules]).unwrap();
|
||||||
|
|
||||||
let object_path = edlang_codegen_llvm::compile(&session, &program_ir)?;
|
let object_path = edlang_codegen_llvm::compile(&session, &program_ir).unwrap();
|
||||||
|
|
||||||
if library {
|
if library {
|
||||||
link_shared_lib(&object_path, &session.output_file)?;
|
link_shared_lib(&[object_path.clone()], &session.output_file).unwrap();
|
||||||
} else {
|
} else {
|
||||||
link_binary(&object_path, &session.output_file)?;
|
link_binary(&[object_path.clone()], &session.output_file).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(CompileResult {
|
Ok(CompileResult {
|
||||||
|
@ -81,5 +79,5 @@ pub fn compile_program(
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run_program(program: &Path, args: &[&str]) -> Result<Child, std::io::Error> {
|
pub fn run_program(program: &Path, args: &[&str]) -> Result<Child, std::io::Error> {
|
||||||
std::process::Command::new(dbg!(program)).args(args).spawn()
|
std::process::Command::new(program).args(args).spawn()
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,6 +39,7 @@ pub struct ProgramBody {
|
||||||
pub struct ModuleBody {
|
pub struct ModuleBody {
|
||||||
pub module_id: DefId,
|
pub module_id: DefId,
|
||||||
pub parent_ids: Vec<DefId>,
|
pub parent_ids: Vec<DefId>,
|
||||||
|
pub file_id: usize,
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub symbols: SymbolTable,
|
pub symbols: SymbolTable,
|
||||||
/// Functions defined in this module.
|
/// Functions defined in this module.
|
||||||
|
|
|
@ -60,6 +60,7 @@ pub struct BodyBuilder {
|
||||||
pub statements: Vec<Statement>,
|
pub statements: Vec<Statement>,
|
||||||
pub name_to_local: HashMap<String, usize>,
|
pub name_to_local: HashMap<String, usize>,
|
||||||
pub ret_local: usize,
|
pub ret_local: usize,
|
||||||
|
pub file_id: usize,
|
||||||
pub ctx: BuildCtx,
|
pub ctx: BuildCtx,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,33 +7,60 @@ use crate::DefId;
|
||||||
#[derive(Debug, Error, Clone)]
|
#[derive(Debug, Error, Clone)]
|
||||||
pub enum LoweringError {
|
pub enum LoweringError {
|
||||||
#[error("module {module:?} not found")]
|
#[error("module {module:?} not found")]
|
||||||
ModuleNotFound { span: Span, module: String },
|
ModuleNotFound {
|
||||||
|
span: Span,
|
||||||
|
module: String,
|
||||||
|
file_id: usize,
|
||||||
|
},
|
||||||
#[error("function {function:?} not found")]
|
#[error("function {function:?} not found")]
|
||||||
FunctionNotFound { span: Span, function: String },
|
FunctionNotFound {
|
||||||
|
span: Span,
|
||||||
|
function: String,
|
||||||
|
file_id: usize,
|
||||||
|
},
|
||||||
#[error("symbol {:?} not found", symbol.name)]
|
#[error("symbol {:?} not found", symbol.name)]
|
||||||
ImportNotFound {
|
ImportNotFound {
|
||||||
module_span: Span,
|
module_span: Span,
|
||||||
import_span: Span,
|
import_span: Span,
|
||||||
symbol: Ident,
|
symbol: Ident,
|
||||||
|
file_id: usize,
|
||||||
},
|
},
|
||||||
#[error("trying to mutate a non-mutable reference")]
|
#[error("trying to mutate a non-mutable reference")]
|
||||||
BorrowNotMutable {
|
BorrowNotMutable {
|
||||||
span: Span,
|
span: Span,
|
||||||
type_span: Option<Span>,
|
type_span: Option<Span>,
|
||||||
name: String,
|
name: String,
|
||||||
|
file_id: usize,
|
||||||
},
|
},
|
||||||
#[error("unrecognized type {name}")]
|
#[error("unrecognized type {name}")]
|
||||||
UnrecognizedType { span: Span, name: String },
|
UnrecognizedType {
|
||||||
|
span: Span,
|
||||||
|
name: String,
|
||||||
|
file_id: usize,
|
||||||
|
},
|
||||||
#[error("id not found")]
|
#[error("id not found")]
|
||||||
IdNotFound { span: Span, id: DefId },
|
IdNotFound {
|
||||||
|
span: Span,
|
||||||
|
id: DefId,
|
||||||
|
file_id: usize,
|
||||||
|
},
|
||||||
#[error("feature not yet implemented: {message}")]
|
#[error("feature not yet implemented: {message}")]
|
||||||
NotYetImplemented { span: Span, message: &'static str },
|
NotYetImplemented {
|
||||||
|
span: Span,
|
||||||
|
message: &'static str,
|
||||||
|
file_id: usize,
|
||||||
|
},
|
||||||
#[error("unexpected type")]
|
#[error("unexpected type")]
|
||||||
UnexpectedType {
|
UnexpectedType {
|
||||||
span: Span,
|
span: Span,
|
||||||
found: TypeKind,
|
found: TypeKind,
|
||||||
expected: TypeInfo,
|
expected: TypeInfo,
|
||||||
|
file_id: usize,
|
||||||
},
|
},
|
||||||
#[error("use of underclared variable {name:?}")]
|
#[error("use of underclared variable {name:?}")]
|
||||||
UseOfUndeclaredVariable { span: Span, name: String },
|
UseOfUndeclaredVariable {
|
||||||
|
span: Span,
|
||||||
|
name: String,
|
||||||
|
file_id: usize,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,27 +15,33 @@ mod common;
|
||||||
pub mod errors;
|
pub mod errors;
|
||||||
mod prepass;
|
mod prepass;
|
||||||
|
|
||||||
pub fn lower_modules(modules: &[ast::Module]) -> Result<ProgramBody, LoweringError> {
|
pub fn lower_modules(modules: &[Vec<ast::Module>]) -> Result<ProgramBody, LoweringError> {
|
||||||
let mut ctx = BuildCtx::default();
|
let mut ctx = BuildCtx::default();
|
||||||
|
|
||||||
// resolve symbols
|
// resolve symbols
|
||||||
for module in modules {
|
for (file_id, modules) in modules.iter().enumerate() {
|
||||||
ctx = prepass::prepass_module(ctx, module)?;
|
for module in modules {
|
||||||
|
ctx = prepass::prepass_module(ctx, module, file_id)?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// resolve imports
|
// resolve imports
|
||||||
for module in modules {
|
for (file_id, modules) in modules.iter().enumerate() {
|
||||||
ctx = prepass::prepass_imports(ctx, module)?;
|
for module in modules {
|
||||||
|
ctx = prepass::prepass_imports(ctx, module, file_id)?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for mod_def in modules {
|
for modules in modules {
|
||||||
let id = *ctx
|
for mod_def in modules {
|
||||||
.body
|
let id = *ctx
|
||||||
.top_level_module_names
|
.body
|
||||||
.get(&mod_def.name.name)
|
.top_level_module_names
|
||||||
.expect("module should exist");
|
.get(&mod_def.name.name)
|
||||||
|
.expect("module should exist");
|
||||||
|
|
||||||
ctx = lower_module(ctx, mod_def, id)?;
|
ctx = lower_module(ctx, mod_def, id)?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(ctx.body)
|
Ok(ctx.body)
|
||||||
|
@ -157,6 +163,10 @@ fn lower_function(
|
||||||
ret_local: 0,
|
ret_local: 0,
|
||||||
name_to_local: HashMap::new(),
|
name_to_local: HashMap::new(),
|
||||||
statements: Vec::new(),
|
statements: Vec::new(),
|
||||||
|
file_id: {
|
||||||
|
let body = ctx.body.modules.get(&module_id).unwrap();
|
||||||
|
body.file_id
|
||||||
|
},
|
||||||
ctx,
|
ctx,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -450,6 +460,7 @@ fn lower_let(builder: &mut BodyBuilder, info: &ast::LetStmt) -> Result<(), Lower
|
||||||
span: info.span,
|
span: info.span,
|
||||||
found: found_ty,
|
found: found_ty,
|
||||||
expected: ty.clone(),
|
expected: ty.clone(),
|
||||||
|
file_id: builder.file_id,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -781,6 +792,7 @@ fn lower_binary_expr(
|
||||||
span: Some(lhs_span),
|
span: Some(lhs_span),
|
||||||
kind: lhs_ty,
|
kind: lhs_ty,
|
||||||
},
|
},
|
||||||
|
file_id: builder.file_id,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1112,6 +1124,7 @@ fn lower_return(
|
||||||
span,
|
span,
|
||||||
found: ty,
|
found: ty,
|
||||||
expected: return_type.clone(),
|
expected: return_type.clone(),
|
||||||
|
file_id: builder.file_id,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1145,6 +1158,7 @@ fn lower_path(
|
||||||
LoweringError::UseOfUndeclaredVariable {
|
LoweringError::UseOfUndeclaredVariable {
|
||||||
span: info.span,
|
span: info.span,
|
||||||
name: info.first.name.clone(),
|
name: info.first.name.clone(),
|
||||||
|
file_id: builder.file_id,
|
||||||
},
|
},
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
@ -1256,6 +1270,7 @@ pub fn lower_type(
|
||||||
Err(LoweringError::UnrecognizedType {
|
Err(LoweringError::UnrecognizedType {
|
||||||
span: t.name.span,
|
span: t.name.span,
|
||||||
name: t.name.name.clone(),
|
name: t.name.name.clone(),
|
||||||
|
file_id: module.file_id,
|
||||||
})?
|
})?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,11 @@ use super::common::BuildCtx;
|
||||||
use edlang_ast as ast;
|
use edlang_ast as ast;
|
||||||
use edlang_ir::ModuleBody;
|
use edlang_ir::ModuleBody;
|
||||||
|
|
||||||
pub fn prepass_module(mut ctx: BuildCtx, mod_def: &ast::Module) -> Result<BuildCtx, LoweringError> {
|
pub fn prepass_module(
|
||||||
|
mut ctx: BuildCtx,
|
||||||
|
mod_def: &ast::Module,
|
||||||
|
file_id: usize,
|
||||||
|
) -> Result<BuildCtx, LoweringError> {
|
||||||
let module_id = ctx.gen.next_defid();
|
let module_id = ctx.gen.next_defid();
|
||||||
tracing::debug!("running ir prepass on module {:?}", module_id);
|
tracing::debug!("running ir prepass on module {:?}", module_id);
|
||||||
|
|
||||||
|
@ -29,6 +33,7 @@ pub fn prepass_module(mut ctx: BuildCtx, mod_def: &ast::Module) -> Result<BuildC
|
||||||
constants: Default::default(),
|
constants: Default::default(),
|
||||||
imports: Default::default(),
|
imports: Default::default(),
|
||||||
span: mod_def.span,
|
span: mod_def.span,
|
||||||
|
file_id,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -106,7 +111,7 @@ pub fn prepass_module(mut ctx: BuildCtx, mod_def: &ast::Module) -> Result<BuildC
|
||||||
.expect("module should exist");
|
.expect("module should exist");
|
||||||
|
|
||||||
let next_id = *current_module.symbols.modules.get(&info.name.name).unwrap();
|
let next_id = *current_module.symbols.modules.get(&info.name.name).unwrap();
|
||||||
ctx = prepass_sub_module(ctx, &[module_id], next_id, info)?;
|
ctx = prepass_sub_module(ctx, &[module_id], next_id, info, file_id)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -118,6 +123,7 @@ pub fn prepass_sub_module(
|
||||||
parent_ids: &[DefId],
|
parent_ids: &[DefId],
|
||||||
module_id: DefId,
|
module_id: DefId,
|
||||||
mod_def: &ast::Module,
|
mod_def: &ast::Module,
|
||||||
|
file_id: usize,
|
||||||
) -> Result<BuildCtx, LoweringError> {
|
) -> Result<BuildCtx, LoweringError> {
|
||||||
tracing::debug!("running ir prepass on submodule {:?}", module_id);
|
tracing::debug!("running ir prepass on submodule {:?}", module_id);
|
||||||
let mut submodule_parents_ids = parent_ids.to_vec();
|
let mut submodule_parents_ids = parent_ids.to_vec();
|
||||||
|
@ -137,6 +143,7 @@ pub fn prepass_sub_module(
|
||||||
types: Default::default(),
|
types: Default::default(),
|
||||||
constants: Default::default(),
|
constants: Default::default(),
|
||||||
span: mod_def.span,
|
span: mod_def.span,
|
||||||
|
file_id,
|
||||||
};
|
};
|
||||||
|
|
||||||
for ct in &mod_def.contents {
|
for ct in &mod_def.contents {
|
||||||
|
@ -201,7 +208,7 @@ pub fn prepass_sub_module(
|
||||||
for ct in &mod_def.contents {
|
for ct in &mod_def.contents {
|
||||||
if let ast::ModuleStatement::Module(info) = ct {
|
if let ast::ModuleStatement::Module(info) = ct {
|
||||||
let next_id = ctx.gen.next_defid();
|
let next_id = ctx.gen.next_defid();
|
||||||
ctx = prepass_sub_module(ctx, &submodule_parents_ids, next_id, info)?;
|
ctx = prepass_sub_module(ctx, &submodule_parents_ids, next_id, info, file_id)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -211,6 +218,7 @@ pub fn prepass_sub_module(
|
||||||
pub fn prepass_imports(
|
pub fn prepass_imports(
|
||||||
mut ctx: BuildCtx,
|
mut ctx: BuildCtx,
|
||||||
mod_def: &ast::Module,
|
mod_def: &ast::Module,
|
||||||
|
file_id: usize,
|
||||||
) -> Result<BuildCtx, LoweringError> {
|
) -> Result<BuildCtx, LoweringError> {
|
||||||
let mod_id = *ctx
|
let mod_id = *ctx
|
||||||
.body
|
.body
|
||||||
|
@ -226,6 +234,7 @@ pub fn prepass_imports(
|
||||||
.ok_or_else(|| LoweringError::ModuleNotFound {
|
.ok_or_else(|| LoweringError::ModuleNotFound {
|
||||||
span: import.module[0].span,
|
span: import.module[0].span,
|
||||||
module: import.module[0].name.clone(),
|
module: import.module[0].name.clone(),
|
||||||
|
file_id,
|
||||||
})?;
|
})?;
|
||||||
let mut imported_module =
|
let mut imported_module =
|
||||||
ctx.body
|
ctx.body
|
||||||
|
@ -234,6 +243,7 @@ pub fn prepass_imports(
|
||||||
.ok_or(LoweringError::IdNotFound {
|
.ok_or(LoweringError::IdNotFound {
|
||||||
span: mod_def.span,
|
span: mod_def.span,
|
||||||
id: *imported_module_id,
|
id: *imported_module_id,
|
||||||
|
file_id,
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
for module_path in import.module.iter().skip(1) {
|
for module_path in import.module.iter().skip(1) {
|
||||||
|
@ -244,11 +254,13 @@ pub fn prepass_imports(
|
||||||
.ok_or_else(|| LoweringError::ModuleNotFound {
|
.ok_or_else(|| LoweringError::ModuleNotFound {
|
||||||
span: module_path.span,
|
span: module_path.span,
|
||||||
module: module_path.name.clone(),
|
module: module_path.name.clone(),
|
||||||
|
file_id,
|
||||||
})?;
|
})?;
|
||||||
imported_module = ctx.body.modules.get(imported_module_id).ok_or({
|
imported_module = ctx.body.modules.get(imported_module_id).ok_or({
|
||||||
LoweringError::IdNotFound {
|
LoweringError::IdNotFound {
|
||||||
span: module_path.span,
|
span: module_path.span,
|
||||||
id: *imported_module_id,
|
id: *imported_module_id,
|
||||||
|
file_id,
|
||||||
}
|
}
|
||||||
})?;
|
})?;
|
||||||
}
|
}
|
||||||
|
@ -269,6 +281,7 @@ pub fn prepass_imports(
|
||||||
module_span: mod_def.span,
|
module_span: mod_def.span,
|
||||||
import_span: import.span,
|
import_span: import.span,
|
||||||
symbol: sym.clone(),
|
symbol: sym.clone(),
|
||||||
|
file_id,
|
||||||
})?;
|
})?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -283,7 +296,7 @@ pub fn prepass_imports(
|
||||||
|
|
||||||
for c in &mod_def.contents {
|
for c in &mod_def.contents {
|
||||||
if let ast::ModuleStatement::Module(info) = c {
|
if let ast::ModuleStatement::Module(info) = c {
|
||||||
ctx = prepass_imports_submodule(ctx, info, mod_id)?;
|
ctx = prepass_imports_submodule(ctx, info, mod_id, file_id)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -294,6 +307,7 @@ pub fn prepass_imports_submodule(
|
||||||
mut ctx: BuildCtx,
|
mut ctx: BuildCtx,
|
||||||
mod_def: &ast::Module,
|
mod_def: &ast::Module,
|
||||||
parent_id: DefId,
|
parent_id: DefId,
|
||||||
|
file_id: usize,
|
||||||
) -> Result<BuildCtx, LoweringError> {
|
) -> Result<BuildCtx, LoweringError> {
|
||||||
let mod_id = *ctx
|
let mod_id = *ctx
|
||||||
.body
|
.body
|
||||||
|
@ -306,6 +320,7 @@ pub fn prepass_imports_submodule(
|
||||||
.ok_or_else(|| LoweringError::ModuleNotFound {
|
.ok_or_else(|| LoweringError::ModuleNotFound {
|
||||||
span: mod_def.span,
|
span: mod_def.span,
|
||||||
module: mod_def.name.name.clone(),
|
module: mod_def.name.name.clone(),
|
||||||
|
file_id,
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
for import in &mod_def.imports {
|
for import in &mod_def.imports {
|
||||||
|
@ -316,11 +331,13 @@ pub fn prepass_imports_submodule(
|
||||||
.ok_or_else(|| LoweringError::ModuleNotFound {
|
.ok_or_else(|| LoweringError::ModuleNotFound {
|
||||||
span: import.module[0].span,
|
span: import.module[0].span,
|
||||||
module: import.module[0].name.clone(),
|
module: import.module[0].name.clone(),
|
||||||
|
file_id,
|
||||||
})?;
|
})?;
|
||||||
let mut imported_module = ctx.body.modules.get(imported_module_id).ok_or_else(|| {
|
let mut imported_module = ctx.body.modules.get(imported_module_id).ok_or_else(|| {
|
||||||
LoweringError::ModuleNotFound {
|
LoweringError::ModuleNotFound {
|
||||||
span: import.module[0].span,
|
span: import.module[0].span,
|
||||||
module: import.module[0].name.clone(),
|
module: import.module[0].name.clone(),
|
||||||
|
file_id,
|
||||||
}
|
}
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
|
@ -332,11 +349,13 @@ pub fn prepass_imports_submodule(
|
||||||
.ok_or_else(|| LoweringError::ModuleNotFound {
|
.ok_or_else(|| LoweringError::ModuleNotFound {
|
||||||
span: module_path.span,
|
span: module_path.span,
|
||||||
module: module_path.name.clone(),
|
module: module_path.name.clone(),
|
||||||
|
file_id,
|
||||||
})?;
|
})?;
|
||||||
imported_module = ctx.body.modules.get(imported_module_id).ok_or({
|
imported_module = ctx.body.modules.get(imported_module_id).ok_or({
|
||||||
LoweringError::IdNotFound {
|
LoweringError::IdNotFound {
|
||||||
span: import.span,
|
span: import.span,
|
||||||
id: *imported_module_id,
|
id: *imported_module_id,
|
||||||
|
file_id,
|
||||||
}
|
}
|
||||||
})?;
|
})?;
|
||||||
}
|
}
|
||||||
|
@ -357,6 +376,7 @@ pub fn prepass_imports_submodule(
|
||||||
module_span: mod_def.span,
|
module_span: mod_def.span,
|
||||||
import_span: import.span,
|
import_span: import.span,
|
||||||
symbol: sym.clone(),
|
symbol: sym.clone(),
|
||||||
|
file_id,
|
||||||
})?;
|
})?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,13 +4,11 @@ use ariadne::Source;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Session {
|
pub struct Session {
|
||||||
pub file_path: PathBuf,
|
pub file_paths: Vec<PathBuf>,
|
||||||
pub debug_info: DebugInfo,
|
pub debug_info: DebugInfo,
|
||||||
pub optlevel: OptLevel,
|
pub optlevel: OptLevel,
|
||||||
pub source: Source<String>,
|
pub sources: Vec<Source<String>>,
|
||||||
pub library: bool,
|
pub library: bool,
|
||||||
/// The directory where to store artifacts and intermediate files such as object files.
|
|
||||||
pub target_dir: PathBuf,
|
|
||||||
pub output_file: PathBuf,
|
pub output_file: PathBuf,
|
||||||
pub output_llvm: bool,
|
pub output_llvm: bool,
|
||||||
pub output_asm: bool,
|
pub output_asm: bool,
|
||||||
|
|
Loading…
Reference in a new issue