Compare commits

...

3 Commits

Author SHA1 Message Date
1acaa29a12 Fix module scopes being linked 2025-07-15 20:09:33 +03:00
6788ef1690 Use AvailableExternally-linkage for externs for imports 2025-07-15 20:01:46 +03:00
6f8c02ac04 Add compilation time to cli 2025-07-15 19:45:03 +03:00
12 changed files with 66 additions and 35 deletions

View File

@ -265,8 +265,15 @@ impl FunctionHolder {
return; return;
} }
if self.data.flags.is_imported && !in_main_module { if self.data.flags.is_imported {
LLVMSetLinkage(own_function.value_ref, LLVMLinkage::LLVMExternalLinkage); if self.data.flags.is_extern {
LLVMSetLinkage(
own_function.value_ref,
LLVMLinkage::LLVMAvailableExternallyLinkage,
);
} else {
LLVMSetLinkage(own_function.value_ref, LLVMLinkage::LLVMExternalLinkage);
}
} else { } else {
LLVMSetLinkage(own_function.value_ref, LLVMLinkage::LLVMPrivateLinkage); LLVMSetLinkage(own_function.value_ref, LLVMLinkage::LLVMPrivateLinkage);
} }

View File

@ -12,6 +12,8 @@ fn main() -> Result<(), std::io::Error> {
let object_path = parent.with_extension("o"); let object_path = parent.with_extension("o");
let asm_path = parent.with_extension("asm"); let asm_path = parent.with_extension("asm");
let before = std::time::SystemTime::now();
let text = fs::read_to_string(&path)?; let text = fs::read_to_string(&path)?;
match compile(&text, PathBuf::from(&path)) { match compile(&text, PathBuf::from(&path)) {
Ok(CompileOutput { Ok(CompileOutput {
@ -20,15 +22,20 @@ fn main() -> Result<(), std::io::Error> {
obj_buffer, obj_buffer,
llvm_ir, llvm_ir,
}) => { }) => {
println!("Compiled with triple: {}", &triple); println!("{}", llvm_ir);
let after = std::time::SystemTime::now();
println!("Compiled with triple: {}\n", &triple);
fs::write(&llvm_ir_path, &llvm_ir).expect("Could not write LLVM IR -file!"); fs::write(&llvm_ir_path, &llvm_ir).expect("Could not write LLVM IR -file!");
println!("Output LLVM IR to {:?}", llvm_ir_path); println!("Output LLVM IR to {:?}", llvm_ir_path);
fs::write(&asm_path, &assembly).expect("Could not write Assembly-file!"); fs::write(&asm_path, &assembly).expect("Could not write Assembly-file!");
println!("Output Assembly to {:?}", asm_path); println!("Output Assembly to {:?}", asm_path);
fs::write(&object_path, &obj_buffer).expect("Could not write Object-file!"); fs::write(&object_path, &obj_buffer).expect("Could not write Object-file!");
println!("Output Object-file to {:?}", object_path); println!("Output Object-file to {:?}\n", object_path);
println!(
println!("{}", llvm_ir); "Compilation took: {:.2}ms\n",
(after.duration_since(before).unwrap().as_micros() as f32) / 1000.
);
} }
Err(e) => panic!("{}", e), Err(e) => panic!("{}", e),
}; };

View File

@ -58,7 +58,7 @@ impl ast::Module {
.cloned() .cloned()
.map(|p| (p.0, p.1.into())) .map(|p| (p.0, p.1.into()))
.collect(), .collect(),
kind: mir::FunctionDefinitionKind::Extern, kind: mir::FunctionDefinitionKind::Extern(false),
}; };
functions.push(def); functions.push(def);
} }

View File

@ -69,12 +69,13 @@ impl mir::Module {
..FunctionFlags::default() ..FunctionFlags::default()
}, },
), ),
mir::FunctionDefinitionKind::Extern => module.function( mir::FunctionDefinitionKind::Extern(imported) => module.function(
&function.name, &function.name,
function.return_type.get_type(), function.return_type.get_type(),
param_types, param_types,
FunctionFlags { FunctionFlags {
is_extern: true, is_extern: true,
is_imported: *imported,
..FunctionFlags::default() ..FunctionFlags::default()
}, },
), ),
@ -117,7 +118,7 @@ impl mir::Module {
} }
} }
} }
mir::FunctionDefinitionKind::Extern => {} mir::FunctionDefinitionKind::Extern(_) => {}
} }
} }

View File

@ -103,13 +103,18 @@ pub fn compile_module(
} }
pub fn perform_all_passes(context: &mut mir::Context) -> Result<(), ReidError> { pub fn perform_all_passes(context: &mut mir::Context) -> Result<(), ReidError> {
#[cfg(debug_assertions)]
dbg!(&context);
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
println!("{}", &context); println!("{}", &context);
let state = context.pass(&mut LinkerPass); let state = context.pass(&mut LinkerPass);
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
println!("{:?}\n{}", &context, &context); println!("{}", &context);
#[cfg(debug_assertions)]
dbg!(&state);
if !state.errors.is_empty() { if !state.errors.is_empty() {
return Err(ReidError::LinkerErrors(state.errors)); return Err(ReidError::LinkerErrors(state.errors));
@ -119,10 +124,10 @@ pub fn perform_all_passes(context: &mut mir::Context) -> Result<(), ReidError> {
let state = context.pass(&mut TypeInference { refs: &refs }); let state = context.pass(&mut TypeInference { refs: &refs });
#[cfg(debug_assertions)]
dbg!(&state, &refs);
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
println!("{}", &context); println!("{}", &context);
#[cfg(debug_assertions)]
dbg!(&state, &refs);
if !state.errors.is_empty() { if !state.errors.is_empty() {
return Err(ReidError::TypeInferenceErrors(state.errors)); return Err(ReidError::TypeInferenceErrors(state.errors));
@ -130,10 +135,10 @@ pub fn perform_all_passes(context: &mut mir::Context) -> Result<(), ReidError> {
let state = context.pass(&mut TypeCheck { refs: &refs }); let state = context.pass(&mut TypeCheck { refs: &refs });
#[cfg(debug_assertions)]
dbg!(&state);
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
println!("{}", &context); println!("{}", &context);
#[cfg(debug_assertions)]
dbg!(&state);
if !state.errors.is_empty() { if !state.errors.is_empty() {
return Err(ReidError::TypeCheckErrors(state.errors)); return Err(ReidError::TypeCheckErrors(state.errors));

View File

@ -61,7 +61,8 @@ impl Display for FunctionDefinitionKind {
write!(f, "{}", block)?; write!(f, "{}", block)?;
Ok(()) Ok(())
} }
Self::Extern => write!(f, "<External>"), Self::Extern(true) => write!(f, "<Imported Extern>"),
Self::Extern(false) => write!(f, "<Linked Extern>"),
} }
} }
} }

View File

@ -193,7 +193,7 @@ impl Pass for LinkerPass {
is_imported: false, is_imported: false,
return_type: func.return_type.clone(), return_type: func.return_type.clone(),
parameters: func.parameters.clone(), parameters: func.parameters.clone(),
kind: super::FunctionDefinitionKind::Extern, kind: super::FunctionDefinitionKind::Extern(true),
}); });
} }
} }

View File

@ -254,21 +254,22 @@ pub struct FunctionDefinition {
pub enum FunctionDefinitionKind { pub enum FunctionDefinitionKind {
/// Actual definition block and surrounding signature range /// Actual definition block and surrounding signature range
Local(Block, Metadata), Local(Block, Metadata),
Extern, /// True = imported from other module, False = Is user defined extern
Extern(bool),
} }
impl FunctionDefinition { impl FunctionDefinition {
fn block_meta(&self) -> Metadata { fn block_meta(&self) -> Metadata {
match &self.kind { match &self.kind {
FunctionDefinitionKind::Local(block, _) => block.meta, FunctionDefinitionKind::Local(block, _) => block.meta,
FunctionDefinitionKind::Extern => Metadata::default(), FunctionDefinitionKind::Extern(_) => Metadata::default(),
} }
} }
fn signature(&self) -> Metadata { fn signature(&self) -> Metadata {
match &self.kind { match &self.kind {
FunctionDefinitionKind::Local(_, metadata) => *metadata, FunctionDefinitionKind::Local(_, metadata) => *metadata,
FunctionDefinitionKind::Extern => Metadata::default(), FunctionDefinitionKind::Extern(_) => Metadata::default(),
} }
} }
} }

View File

@ -210,7 +210,7 @@ impl Context {
let mut scope = Scope::default(); let mut scope = Scope::default();
pass.context(self, PassState::from(&mut state, &mut scope)); pass.context(self, PassState::from(&mut state, &mut scope));
for module in &mut self.modules { for module in &mut self.modules {
module.pass(pass, &mut state, &mut scope); module.pass(pass, &mut state, &mut scope.inner());
} }
state state
} }
@ -261,7 +261,7 @@ impl FunctionDefinition {
scope.return_type_hint = Some(self.return_type.clone()); scope.return_type_hint = Some(self.return_type.clone());
block.pass(pass, state, scope); block.pass(pass, state, scope);
} }
FunctionDefinitionKind::Extern => {} FunctionDefinitionKind::Extern(_) => {}
}; };
} }
} }

View File

@ -94,7 +94,7 @@ impl FunctionDefinition {
state.scope.return_type_hint = Some(self.return_type.clone()); state.scope.return_type_hint = Some(self.return_type.clone());
block.typecheck(&mut state.inner(), &hints, Some(&return_type)) block.typecheck(&mut state.inner(), &hints, Some(&return_type))
} }
FunctionDefinitionKind::Extern => { FunctionDefinitionKind::Extern(_) => {
Ok((ReturnKind::Soft, TypeKind::Vague(Vague::Unknown))) Ok((ReturnKind::Soft, TypeKind::Vague(Vague::Unknown)))
} }
}; };

View File

@ -64,7 +64,7 @@ impl FunctionDefinition {
ret_ty.narrow(&scope_hints.from_type(&self.return_type).unwrap()); ret_ty.narrow(&scope_hints.from_type(&self.return_type).unwrap());
} }
} }
FunctionDefinitionKind::Extern => {} FunctionDefinitionKind::Extern(_) => {}
}; };
Ok(()) Ok(())

View File

@ -181,14 +181,16 @@ impl IndexedVariableReference {
} }
} }
#[derive(Debug, Clone, Copy, thiserror::Error)] #[derive(Debug, Clone, thiserror::Error)]
pub enum EqualsIssue { pub enum EqualsIssue {
#[error("Function is already defined locally at {:?}", (.0).range)] #[error("Function is already defined locally at {:?}", (.0).range)]
ExistsLocally(Metadata), ExistsLocally(Metadata),
#[error("asd")] #[error("Equals")]
Equals, Equals,
#[error("asd")] #[error("Function {0} is already declared locally at {:?}", (.1).range)]
ConflictingImports, AlreadyExtern(String, Metadata),
#[error("Function {0} is already imported from another module")]
ConflictWithImport(String),
} }
impl FunctionDefinition { impl FunctionDefinition {
@ -197,15 +199,22 @@ impl FunctionDefinition {
FunctionDefinitionKind::Local(_, metadata) => { FunctionDefinitionKind::Local(_, metadata) => {
Err(EqualsIssue::ExistsLocally(*metadata)) Err(EqualsIssue::ExistsLocally(*metadata))
} }
FunctionDefinitionKind::Extern => { FunctionDefinitionKind::Extern(imported) => {
if self.is_pub == other.is_pub if *imported {
&& self.name == other.name Err(EqualsIssue::ConflictWithImport(self.name.clone()))
&& self.parameters == other.parameters
&& self.return_type == other.return_type
{
Ok(())
} else { } else {
Err(EqualsIssue::ConflictingImports) if self.is_pub == other.is_pub
&& self.name == other.name
&& self.parameters == other.parameters
&& self.return_type == other.return_type
{
Ok(())
} else {
Err(EqualsIssue::AlreadyExtern(
self.name.clone(),
self.signature(),
))
}
} }
} }
} }