Skip to content

Commit

Permalink
Make some tweaks to compile compiler_builtins (#139)
Browse files Browse the repository at this point in the history
The final of the Rust core libraries is the library of compiler
builtins, which needs to be compiled as it is depended upon by both
`core` and `alloc`. In order to get this compiling, a raft of small
changes have been made. These are:

- Adds the apparently-required `half` and `fp128` type support
  throughout the codebase.
- Fixes a parsing bug in the `integer` parser that omitted certain valid
  negative integer numbers.
- Fixes a bug in the float parsing logic for LLVM types.
  • Loading branch information
iamrecursion authored Jan 31, 2025
1 parent 83909f2 commit 9396eb6
Show file tree
Hide file tree
Showing 11 changed files with 95 additions and 31 deletions.
23 changes: 23 additions & 0 deletions crates/compiler/src/llvm/typesystem.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,9 @@ pub enum LLVMType {
/// The IEEE-754 `binary64` [floating point type](https://llvm.org/docs/LangRef.html#floating-point-types).
f64,

/// The IEEE-754 `binary128` [floating point type](https://llvm.org/docs/LangRef.html#floating-point-types).
f128,

/// Used to specify locations in memory as described in the
/// [LLVM IR reference](https://llvm.org/docs/LangRef.html#pointer-type).
///
Expand Down Expand Up @@ -184,6 +187,7 @@ impl LLVMType {
| Self::f16
| Self::f32
| Self::f64
| Self::f128
| Self::ptr
| Self::void
| Self::Metadata
Expand Down Expand Up @@ -249,6 +253,7 @@ impl LLVMType {
LLVMType::f16 => 16,
LLVMType::f32 => 32,
LLVMType::f64 => 64,
LLVMType::f128 => 128,
LLVMType::ptr => data_layout.default_pointer_layout().size,
LLVMType::void => 0,
LLVMType::Array(array_type) => array_type.size_of(data_layout),
Expand Down Expand Up @@ -335,6 +340,10 @@ impl LLVMType {
AlignType::ABI => data_layout.expect_float_spec_of(64).abi_alignment,
AlignType::Preferred => data_layout.expect_float_spec_of(64).preferred_alignment,
},
LLVMType::f128 => match align_type {
AlignType::ABI => data_layout.expect_float_spec_of(128).abi_alignment,
AlignType::Preferred => data_layout.expect_float_spec_of(128).preferred_alignment,
},
LLVMType::ptr => match align_type {
AlignType::ABI => data_layout.default_pointer_layout().abi_alignment,
AlignType::Preferred => data_layout.default_pointer_layout().preferred_alignment,
Expand Down Expand Up @@ -368,6 +377,7 @@ impl Display for LLVMType {
LLVMType::f16 => "f16".to_string(),
LLVMType::f32 => "f32".to_string(),
LLVMType::f64 => "f64".to_string(),
LLVMType::f128 => "f128".to_string(),
LLVMType::ptr => "ptr".to_string(),
LLVMType::void => "void".to_string(),
LLVMType::Metadata => "metadata".to_string(),
Expand Down Expand Up @@ -471,6 +481,7 @@ impl<'ctx> TryFrom<&FloatType<'ctx>> for LLVMType {
LLVMTypeKind::LLVMHalfTypeKind => Self::f16,
LLVMTypeKind::LLVMFloatTypeKind => Self::f32,
LLVMTypeKind::LLVMDoubleTypeKind => Self::f64,
LLVMTypeKind::LLVMFP128TypeKind => Self::f128,
_ => Err(Error::UnsupportedType(value.to_string()))?,
};
Ok(ret_val)
Expand Down Expand Up @@ -1197,6 +1208,12 @@ mod test {
assert_eq!(LLVMType::f64.store_size_of(&dl()), 64);
}

#[test]
fn calculates_correct_size_for_f128() {
assert_eq!(LLVMType::f128.size_of(&dl()), 128);
assert_eq!(LLVMType::f128.store_size_of(&dl()), 128);
}

#[test]
fn calculates_correct_size_for_ptr() {
assert_eq!(LLVMType::ptr.size_of(&dl()), 64);
Expand Down Expand Up @@ -1328,6 +1345,12 @@ mod test {
assert_eq!(LLVMType::f64.align_of(Preferred, &dl()), 64);
}

#[test]
fn calculates_correct_alignment_for_f128() {
assert_eq!(LLVMType::f128.align_of(ABI, &dl()), 128);
assert_eq!(LLVMType::f128.align_of(Preferred, &dl()), 128);
}

#[test]
fn calculates_correct_alignment_for_ptr() {
assert_eq!(LLVMType::ptr.align_of(ABI, &dl()), 64);
Expand Down
5 changes: 2 additions & 3 deletions crates/compiler/src/obj_gen/data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -302,11 +302,10 @@ impl ObjectContext {
LLVMType::i48 => Type::Signed48,
LLVMType::i64 => Type::Signed64,
LLVMType::i128 => Type::Signed128,
LLVMType::f16 => Err(Error::invalid_type_conversion(
"We do not currently support half-precision floats",
))?,
LLVMType::f16 => Type::Half,
LLVMType::f32 => Type::Float,
LLVMType::f64 => Type::Double,
LLVMType::f128 => Type::Quad,
LLVMType::ptr => Type::Pointer,
LLVMType::void => Type::Void,
LLVMType::Array(array) => array_to_flo(array)?,
Expand Down
4 changes: 2 additions & 2 deletions crates/compiler/src/obj_gen/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1572,7 +1572,7 @@ impl ObjectGenerator {
// primitive types (the numerics and pointers). To that end, we have to handle
// the store differently based on the type being stored.
match &typ {
bool | i8 | i16 | i24 | i32 | i40 | i48 | i64 | i128 | f16 | f32 | f64 | ptr => {
bool | i8 | i16 | i24 | i32 | i40 | i48 | i64 | i128 | f16 | f32 | f64 | f128 | ptr => {
self.store_primitive(typ, stored_value, pointer, initial_offset, bb)?;
}
Array(array_type) => {
Expand Down Expand Up @@ -1808,7 +1808,7 @@ impl ObjectGenerator {
use LLVMType::*;

match &typ {
bool | i8 | i16 | i24 | i32 | i40 | i48 | i64 | i128 | f16 | f32 | f64 | ptr => {
bool | i8 | i16 | i24 | i32 | i40 | i48 | i64 | i128 | f16 | f32 | f64 | f128 | ptr => {
self.load_primitive_into(target, typ, pointer, initial_offset, bb)?;
}
Array(array_type) => {
Expand Down
14 changes: 14 additions & 0 deletions crates/compiler/src/parser/integer_constant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,20 @@ mod test {
IntegerConstant::parser().parse("i24 -37"),
Ok(IntegerConstant::new(LLVMType::i24, -37))
);
assert_eq!(
IntegerConstant::parser().parse("i128 -4176471573560389552232087451844504212"),
Ok(IntegerConstant::new(
LLVMType::i128,
-4_176_471_573_560_389_552_232_087_451_844_504_212
))
);
assert_eq!(
IntegerConstant::parser().parse("i128 -170141183460469231731687303715884105728"),
Ok(IntegerConstant::new(
LLVMType::i128,
-170_141_183_460_469_231_731_687_303_715_884_105_728
))
);

// Failures
assert!(IntegerConstant::parser().parse("i64 a1").is_err());
Expand Down
22 changes: 10 additions & 12 deletions crates/compiler/src/parser/number.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,23 +8,21 @@ use crate::parser::SimpleParser;

/// Parses a positive or negative integer in the specified `radix`.
#[must_use]
pub fn integer<T>(radix: u32) -> impl SimpleParser<T>
where
T: FromStr + std::ops::Neg<Output = T>,
{
pub fn integer<T: FromStr>(radix: u32) -> impl SimpleParser<T> {
just("-")
.or_not()
.then(text::int(radix))
.try_map(|(uminus, num): (_, String), span| {
let parsed_num = num
.parse::<T>()
.map_err(|_| Simple::custom(span, format!("Could not parse {num} as an i128")))?;
let minus = uminus.unwrap_or_default();
let actual_num = format!("{minus}{num}");
let parsed_num = actual_num.parse::<T>().map_err(|_| {
Simple::custom(
span,
format!("Could not parse {num} as an {}", std::any::type_name::<T>()),
)
})?;

if uminus.is_some() {
Ok(-parsed_num)
} else {
Ok(parsed_num)
}
Ok(parsed_num)
})
}

Expand Down
24 changes: 15 additions & 9 deletions crates/compiler/src/parser/typ.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,18 +24,21 @@ pub fn integer() -> impl crate::parser::SimpleParser<LLVMType> {
just("8").to(LLVMType::i8),
just("24").to(LLVMType::i24),
just("32").to(LLVMType::i32),
just("48").to(LLVMType::i48),
just("40").to(LLVMType::i40),
just("64").to(LLVMType::i64),
)))
}

/// Parses a floating point type from the LLVM IR source text.
#[must_use]
pub fn float() -> impl crate::parser::SimpleParser<LLVMType> {
just("f").ignore_then(choice((
just("16").to(LLVMType::f16),
just("32").to(LLVMType::f32),
just("64").to(LLVMType::f64),
)))
choice((
just("half").to(LLVMType::f16),
just("float").to(LLVMType::f32),
just("double").to(LLVMType::f64),
just("fp128").to(LLVMType::f128),
))
}

/// Parses a void type from the LLVM IR source text.
Expand Down Expand Up @@ -130,6 +133,8 @@ mod test {
assert_eq!(super::integer().parse("i16"), Ok(LLVMType::i16));
assert_eq!(super::integer().parse("i24"), Ok(LLVMType::i24));
assert_eq!(super::integer().parse("i32"), Ok(LLVMType::i32));
assert_eq!(super::integer().parse("i40"), Ok(LLVMType::i40));
assert_eq!(super::integer().parse("i48"), Ok(LLVMType::i48));
assert_eq!(super::integer().parse("i64"), Ok(LLVMType::i64));
assert_eq!(super::integer().parse("i128"), Ok(LLVMType::i128));

Expand All @@ -141,9 +146,10 @@ mod test {
#[test]
fn can_parse_float_types() {
// Successes
assert_eq!(super::float().parse("f16"), Ok(LLVMType::f16));
assert_eq!(super::float().parse("f32"), Ok(LLVMType::f32));
assert_eq!(super::float().parse("f64"), Ok(LLVMType::f64));
assert_eq!(super::float().parse("half"), Ok(LLVMType::f16));
assert_eq!(super::float().parse("float"), Ok(LLVMType::f32));
assert_eq!(super::float().parse("double"), Ok(LLVMType::f64));
assert_eq!(super::float().parse("fp128"), Ok(LLVMType::f128));

// Failures
assert!(super::float().parse("f31").is_err());
Expand Down Expand Up @@ -338,7 +344,7 @@ mod test {
fn can_parse_any_type() {
// Successes
assert_eq!(super::any().parse("i1"), Ok(LLVMType::bool));
assert_eq!(super::any().parse("f64"), Ok(LLVMType::f64));
assert_eq!(super::any().parse("double"), Ok(LLVMType::f64));
assert_eq!(super::any().parse("void"), Ok(LLVMType::void));
assert_eq!(
super::any().parse("[1 x i8]"),
Expand Down
4 changes: 2 additions & 2 deletions crates/compiler/src/polyfill.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1197,7 +1197,7 @@ impl PolyfillMap {
/// Gets the types that we want to generate floating-point operations over.
#[must_use]
pub fn float_types() -> Vec<LLVMType> {
vec![LLVMType::f16, LLVMType::f32, LLVMType::f64]
vec![LLVMType::f16, LLVMType::f32, LLVMType::f64, LLVMType::f128]
}

/// Gets all the numeric types that we want to potentially generate
Expand Down Expand Up @@ -1256,6 +1256,6 @@ mod test {
fn has_correct_polyfill_count() {
let polyfills = PolyfillMap::new();
let count = polyfills.iter().count();
assert_eq!(count, 1379);
assert_eq!(count, 1559);
}
}
17 changes: 17 additions & 0 deletions crates/compiler/tests/compilation_compiler_builtins.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
//! Tests compilation of `compiler_builtins.ll` the Rust core library.
mod common;

#[test]
fn compiles_compiler_builtins() -> miette::Result<()> {
// We start by constructing and running the compiler
common::set_miette_reporting()?;

let compiler = common::default_compiler_from_path("input/compilation/compiler_builtins.ll")?;
let flo = compiler.run()?;

// There should be 1408 functions in the context.
assert_eq!(common::count_functions(&flo, false), 1408);

Ok(())
}
5 changes: 4 additions & 1 deletion crates/compiler/tests/compilation_constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@ fn compiles_constants() -> miette::Result<()> {
// We start by constructing and running the compiler
common::set_miette_reporting()?;
let compiler = common::default_compiler_from_path("input/compilation/constants.ll")?;
let _flo = compiler.run()?;
let flo = compiler.run()?;

// There should be 8 functions in the context.
assert_eq!(common::count_functions(&flo, false), 8);

Ok(())
}
2 changes: 2 additions & 0 deletions crates/flo/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -524,8 +524,10 @@ pub enum Type {
WeaklyTypedFelt,

// Floating point types.
Half,
Float,
Double,
Quad,

// Pointer-ish types.
Pointer,
Expand Down
6 changes: 4 additions & 2 deletions crates/mangler/src/mapping.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,16 +85,18 @@ pub fn mangle_type(typ: &Type) -> Result<String> {
Type::Unsigned64 => "Q",
Type::Unsigned128 => "O",
Type::Signed8 => "b",
Type::Signed16 => "h",
Type::Signed16 => "z",
Type::Signed24 => "x",
Type::Signed32 => "i",
Type::Signed40 => "n",
Type::Signed48 => "k",
Type::Signed64 => "q",
Type::Signed64 => "l",
Type::Signed128 => "o",
Type::WeaklyTypedFelt => "w",
Type::Half => "h",
Type::Float => "f",
Type::Double => "d",
Type::Quad => "q",
Type::Pointer => "p",
Type::Snapshot(snap) => &mangle_snapshot(snap.as_ref())?,
Type::Array(array_ty) => &mangle_array(array_ty)?,
Expand Down

0 comments on commit 9396eb6

Please sign in to comment.