Skip to content

Commit 3475a64

Browse files
authored
Merge pull request #131 from cobalt-language/looser-llvm
Loosen LLVM requirements
2 parents f8d778a + da46438 commit 3475a64

File tree

7 files changed

+73
-24
lines changed

7 files changed

+73
-24
lines changed

cobalt-ast/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,4 @@ inventory = "0.3.12"
2424
once_cell = "1.18.0"
2525
hashbrown = "0.14.2"
2626
flurry = "0.4.0"
27+
thiserror = "1.0.51"

cobalt-ast/src/context.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,21 @@ use std::cell::{Cell, RefCell};
99
use std::io::{self, BufRead, Read, Write};
1010
use std::mem::MaybeUninit;
1111
use std::pin::Pin;
12+
use thiserror::Error;
13+
14+
type HeaderVersionType = u16;
15+
/// Simple number to check if a header is compatible for loading
16+
/// Bump this whenever a breaking change is made to the format
17+
const HEADER_FMT_VERSION: HeaderVersionType = 0;
18+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Error)]
19+
#[error("expected header version {HEADER_FMT_VERSION}, found version {0}")]
20+
pub struct HeaderVersionError(pub HeaderVersionType);
21+
impl From<HeaderVersionError> for io::Error {
22+
fn from(value: HeaderVersionError) -> Self {
23+
io::Error::new(io::ErrorKind::Other, value)
24+
}
25+
}
26+
1227
#[derive(Clone, PartialEq, Eq, Debug)]
1328
pub struct Flags {
1429
pub word_size: u16,
@@ -17,6 +32,7 @@ pub struct Flags {
1732
pub dbg_mangle: bool,
1833
pub all_move_metadata: bool,
1934
pub private_syms: bool,
35+
pub skip_header_version_check: bool,
2036
}
2137
impl Default for Flags {
2238
fn default() -> Self {
@@ -27,9 +43,11 @@ impl Default for Flags {
2743
dbg_mangle: false,
2844
all_move_metadata: false,
2945
private_syms: true,
46+
skip_header_version_check: false,
3047
}
3148
}
3249
}
50+
3351
pub struct CompCtx<'src, 'ctx> {
3452
pub flags: Flags,
3553
pub context: &'ctx Context,
@@ -277,6 +295,7 @@ impl<'src, 'ctx> CompCtx<'src, 'ctx> {
277295
Some(v)
278296
}
279297
pub fn save<W: Write>(&self, out: &mut W) -> io::Result<()> {
298+
out.write_all(&HEADER_FMT_VERSION.to_be_bytes())?;
280299
for info in inventory::iter::<types::TypeLoader> {
281300
out.write_all(&info.kind.get().to_be_bytes())?;
282301
(info.save_header)(out)?;
@@ -285,6 +304,14 @@ impl<'src, 'ctx> CompCtx<'src, 'ctx> {
285304
self.with_vars(|v| v.save(out))
286305
}
287306
pub fn load<R: Read + BufRead>(&self, buf: &mut R) -> io::Result<Vec<Cow<'src, str>>> {
307+
{
308+
let mut arr = [0; std::mem::size_of::<HeaderVersionType>()];
309+
buf.read_exact(&mut arr)?;
310+
let version = HeaderVersionType::from_be_bytes(arr);
311+
if !(self.flags.skip_header_version_check || version == HEADER_FMT_VERSION) {
312+
Err(HeaderVersionError(version))?;
313+
}
314+
}
288315
let mut out = vec![];
289316
while !buf.fill_buf()?.is_empty() {
290317
let mut bytes = [0u8; 8];

cobalt-build/Cargo.toml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ object = { version = "0.32.1", features = ["write"] }
3131
anyhow = "1.0.75"
3232
anyhow-std = "0.1.4"
3333
thiserror = "1.0.50"
34-
llvm-sys = "160"
3534
lasso = { version = "0.7.2", features = ["multi-threaded"] }
3635
indexmap = "2.0.2"
3736
os_str_bytes = { version = "6.6.1", features = ["conversions"] }
@@ -51,4 +50,4 @@ config-json = ["serde_json"]
5150
config-all = ["config-toml", "config-json"]
5251
cc-build = ["cc"]
5352
build-default = ["cc-build", "config-all"]
54-
default = ["build-default"]
53+
default = ["build-default"]

cobalt-cli/src/lib.rs

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1744,8 +1744,12 @@ pub fn driver(cli: Cli) -> anyhow::Result<()> {
17441744
reporter.insts_after += insts(&ctx.module);
17451745
let input = PathBuf::from(file.name());
17461746
let mut out = match &output {
1747-
None => input,
1748-
Some(p) => p.join(input),
1747+
None => ClioPath::new(input)?,
1748+
Some(p) => {
1749+
let mut p = p.clone();
1750+
p.push(input);
1751+
p
1752+
}
17491753
};
17501754
if !matches!(
17511755
emit,
@@ -1763,7 +1767,7 @@ pub fn driver(cli: Cli) -> anyhow::Result<()> {
17631767
let mut buf = vec![];
17641768
*reporter.cg_time.get_or_insert(Duration::ZERO) +=
17651769
try_timeit(|| ctx.save(&mut buf))?.1;
1766-
Path::new(&out).write_anyhow(buf)?;
1770+
out.create_with_len(buf.len() as _)?.write_all(&buf)?;
17671771
Zero
17681772
}
17691773
OutputType::HeaderObj => {
@@ -1774,21 +1778,22 @@ pub fn driver(cli: Cli) -> anyhow::Result<()> {
17741778
obj.write()
17751779
})?;
17761780
*reporter.cg_time.get_or_insert(Duration::ZERO) += cg_time;
1777-
Path::new(&out).write_anyhow(vec)?;
1781+
out.create_with_len(vec.len() as _)?.write_all(&vec)?;
17781782
Zero
17791783
}
17801784
OutputType::Llvm => {
17811785
out.set_extension("ll");
17821786
let (m, cg_time) = timeit(|| ctx.module.to_string());
17831787
*reporter.cg_time.get_or_insert(Duration::ZERO) += cg_time;
1784-
Path::new(&out).write_anyhow(m)?;
1788+
out.create_with_len(m.len() as _)?.write_all(m.as_bytes())?;
17851789
Zero
17861790
}
17871791
OutputType::Bitcode => {
17881792
out.set_extension("bc");
17891793
let (m, cg_time) = timeit(|| ctx.module.write_bitcode_to_memory());
17901794
*reporter.cg_time.get_or_insert(Duration::ZERO) += cg_time;
1791-
Path::new(&out).write_anyhow(m.as_slice())?;
1795+
out.create_with_len(m.get_size() as _)?
1796+
.write_all(m.as_slice())?;
17921797
Zero
17931798
}
17941799
OutputType::Assembly => {
@@ -1802,7 +1807,8 @@ pub fn driver(cli: Cli) -> anyhow::Result<()> {
18021807
.unwrap()
18031808
});
18041809
*reporter.cg_time.get_or_insert(Duration::ZERO) += cg_time;
1805-
Path::new(&out).write_anyhow(m.as_slice())?;
1810+
out.create_with_len(m.get_size() as _)?
1811+
.write_all(m.as_slice())?;
18061812
Zero
18071813
}
18081814
_ => {
@@ -1838,16 +1844,17 @@ pub fn driver(cli: Cli) -> anyhow::Result<()> {
18381844
out.set_extension("o");
18391845
archive.as_mut().unwrap().append(
18401846
&ar::Header::new(
1841-
out.into_raw_vec(),
1842-
mb.as_slice().len() as _,
1847+
out.to_os_string().into_raw_vec(),
1848+
mb.get_size() as _,
18431849
),
18441850
mb.as_slice(),
18451851
)?;
18461852
Zero
18471853
}
18481854
OutputType::RawObject => {
18491855
out.set_extension("raw.o");
1850-
std::fs::write(out, mb.as_slice())?;
1856+
out.create_with_len(mb.get_size() as _)?
1857+
.write_all(mb.as_slice())?;
18511858
Zero
18521859
}
18531860
OutputType::Object => {
@@ -1858,7 +1865,7 @@ pub fn driver(cli: Cli) -> anyhow::Result<()> {
18581865
obj::get_writeable_object_from_file(parsed_llvm_object);
18591866
libs::populate_header(&mut writeable_object, &ctx);
18601867
let buf = writeable_object.write()?;
1861-
Path::new(&out).write_anyhow(buf)?;
1868+
out.create_with_len(buf.len() as _)?.write_all(&buf)?;
18621869
Zero
18631870
}
18641871
x => unreachable!("{x:?} has already been handled"),

cobalt-llvm/Cargo.toml

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,9 @@ description.workspace = true
99
documentation.workspace = true
1010

1111
[dependencies]
12-
inkwell = { version = "0.2.0", features = ["llvm16-0"] }
13-
llvm-sys = "160"
12+
inkwell = { version = "0.2.0" }
13+
llvm-sys-15 = { package = "llvm-sys", version = "150", optional = true }
14+
llvm-sys-16 = { package = "llvm-sys", version = "160", optional = true }
1415

1516
[build-dependencies]
1617
lazy_static = "1.4"
@@ -20,12 +21,15 @@ semver = "1.0"
2021

2122
# features passed to llvm-sys
2223
[features]
24+
llvm-15 = ["llvm-sys-15", "inkwell/llvm15-0"]
25+
llvm-16 = ["llvm-sys-16", "inkwell/llvm16-0"]
26+
2327
default = ["llvm-default"]
24-
llvm-default = ["strict-versioning", "prefer-dynamic"]
25-
strict-versioning = ["llvm-sys/strict-versioning"]
26-
no-llvm-linking = ["llvm-sys/no-llvm-linking"]
28+
llvm-default = ["llvm-15", "prefer-dynamic"]
29+
strict-versioning = ["llvm-sys-15?/strict-versioning", "llvm-sys-16?/strict-versioning"]
30+
no-llvm-linking = ["llvm-sys-15?/no-llvm-linking", "llvm-sys-16?/no-llvm-linking"]
2731

28-
prefer-dynamic = ["llvm-sys/prefer-dynamic"]
29-
force-dynamic = ["llvm-sys/force-dynamic"]
30-
prefer-static = ["llvm-sys/prefer-static"]
31-
force-static = ["llvm-sys/force-static"]
32+
prefer-dynamic = ["llvm-sys-15?/prefer-dynamic", "llvm-sys-16?/prefer-dynamic"]
33+
force-dynamic = ["llvm-sys-15?/force-dynamic", "llvm-sys-16?/force-dynamic"]
34+
prefer-static = ["llvm-sys-15?/prefer-static", "llvm-sys-16?/prefer-static"]
35+
force-static = ["llvm-sys-15?/force-static", "llvm-sys-16?/force-static"]

cobalt-llvm/build.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
// This file is the same as llvm-sys's, with some slight modifications to make it run as a submodule.
22
// Notable changes:
3-
// - Linking method is prefer-dynamic by default
3+
// - LLVM version is chosen from features
4+
// - No linking is actually done here
5+
// - Cargo variables are set
46
// - Small refactors have been made to satisfy Clippy
57

68
use const_format::formatcp;
@@ -13,6 +15,9 @@ use std::io::{self, ErrorKind};
1315
use std::path::PathBuf;
1416
use std::process::Command;
1517

18+
#[cfg(feature = "llvm-15")]
19+
const LLVM_MAJOR: u64 = 15;
20+
#[cfg(feature = "llvm-16")]
1621
const LLVM_MAJOR: u64 = 16;
1722

1823
// Environment variables that can guide compilation

cobalt-llvm/src/lib.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
11
pub use inkwell;
2-
pub use llvm_sys;
2+
#[cfg(feature = "llvm-15")]
3+
pub use llvm_sys_15 as llvm_sys;
4+
#[cfg(feature = "llvm-16")]
5+
pub use llvm_sys_16 as llvm_sys;
6+
7+
#[cfg(all(feature = "llvm-15", feature = "llvm-16"))]
8+
compile_error!("LLVM 15 and 16 cannot both be enabled!");
39

410
pub const LLVM_VERSION: &str = env!("LLVM_VERSION");

0 commit comments

Comments
 (0)