Skip to content

Commit c429d67

Browse files
committed
Implemented C integer promotion for systems with 16-bit short and 32-bit int
1 parent 566640d commit c429d67

File tree

6 files changed

+69
-122
lines changed

6 files changed

+69
-122
lines changed

src/asg/datatype/kind/mod.rs

-12
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ use super::Type;
66
use crate::{
77
asg::{human_name::HumanName, Asg, EnumRef, StructRef, TraitRef, TypeAliasRef},
88
ast::{fmt_c_integer, CInteger, FloatSize, IntegerBits, IntegerSign},
9-
c::implicit_conversions::IntegerRank,
109
source_files::Source,
1110
target::Target,
1211
};
@@ -78,17 +77,6 @@ impl TypeKind {
7877
}
7978
}
8079

81-
pub fn integer_rank(&self) -> Option<IntegerRank> {
82-
match self {
83-
TypeKind::Boolean => Some(IntegerRank::Bool),
84-
TypeKind::Integer(integer_bits, _) => Some(IntegerRank::Fixed(integer_bits.bits())),
85-
TypeKind::CInteger(c_integer, _) => Some(IntegerRank::Flexible(*c_integer)),
86-
TypeKind::SizeInteger(_) => Some(IntegerRank::Size),
87-
TypeKind::IntegerLiteral(_) => Some(IntegerRank::Flexible(CInteger::Int)),
88-
_ => None,
89-
}
90-
}
91-
9280
pub fn sign(&self, target: Option<&Target>) -> Option<IntegerSign> {
9381
match self {
9482
TypeKind::Boolean => Some(IntegerSign::Unsigned),

src/asg/datatype/mod.rs

+1-5
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
pub mod kind;
22

3-
use crate::{c::implicit_conversions::IntegerRank, source_files::Source};
3+
use crate::source_files::Source;
44
use core::hash::Hash;
55
pub use kind::*;
66
use std::fmt::Display;
@@ -28,10 +28,6 @@ impl Type {
2828
pub fn is_ambiguous(&self) -> bool {
2929
self.kind.is_ambiguous()
3030
}
31-
32-
pub fn integer_rank(self: &Type) -> Option<IntegerRank> {
33-
self.kind.integer_rank()
34-
}
3531
}
3632

3733
impl PartialEq for Type {

src/c/implicit_conversions/mod.rs

-92
This file was deleted.

src/c/mod.rs

-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
pub mod ast;
22
pub mod encoding;
3-
pub mod implicit_conversions;
43
pub mod lexer;
54
pub mod parser;
65
pub mod preprocessor;

src/lower/mod.rs

+13
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use self::error::LowerError;
1212
use crate::{
1313
asg::Asg,
1414
cli::BuildOptions,
15+
data_units::ByteUnits,
1516
ir::{self},
1617
resolve::PolyRecipe,
1718
};
@@ -22,6 +23,18 @@ use structure::lower_struct;
2223
pub fn lower<'a>(options: &BuildOptions, asg: &Asg) -> Result<ir::Module, LowerError> {
2324
let mut ir_module = ir::Module::new(options.target.clone());
2425

26+
assert_eq!(
27+
ir_module.target.short_layout().width,
28+
ByteUnits::of(2),
29+
"This target is not supported. Adept currently assumes that shorts are 16-bit integers (for integer promotion rules). Which does not hold for this target."
30+
);
31+
32+
assert_eq!(
33+
ir_module.target.int_layout().width,
34+
ByteUnits::of(4),
35+
"This target is not supported. Adept currently assumes that ints are 32-bit integers (for integer promotion rules). Which does not hold for this target."
36+
);
37+
2538
for (struct_ref, structure) in asg.structs.iter() {
2639
lower_struct(&mut ir_module, struct_ref, structure, asg)?;
2740
}

src/resolve/expr/mod.rs

+55-12
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,12 @@ use super::{
2525
Initialized, ResolveTypeCtx,
2626
};
2727
use crate::{
28-
asg::{self, Asg, Expr, ExprKind, FuncRef, StructRef, TypeKind, TypedExpr},
28+
asg::{self, Asg, Cast, CastFrom, Expr, ExprKind, FuncRef, StructRef, TypeKind, TypedExpr},
2929
ast::{
3030
self, CInteger, CIntegerAssumptions, ConformBehavior, IntegerKnown, Language, Settings,
3131
UnaryOperator,
3232
},
33+
data_units::BitUnits,
3334
ir::IntegerSign,
3435
resolve::{
3536
error::ResolveErrorKind,
@@ -447,6 +448,8 @@ pub fn resolve_expr(
447448
asg::ExprKind::Continue.at(source),
448449
)),
449450
ast::ExprKind::IntegerPromote(value) => {
451+
// NOTE: Since this expression comes from C, there
452+
// should not be any untyped literals.
450453
let inner = resolve_expr(
451454
ctx,
452455
value,
@@ -455,19 +458,59 @@ pub fn resolve_expr(
455458
ResolveExprMode::RequireValue,
456459
)?;
457460

458-
let rank = inner.ty.integer_rank();
461+
// WARNING: For now, we assume that shorts are 16 bits and ints are 32 bits
462+
// since this is the case for the vast majority of systems.
463+
// Targets where this does not hold will not be supported for now.
464+
// If we do wish to support them in the future,
465+
// We will probably need to add new types such as promoted<T> and arith<A, B>
466+
// to represent the possible result types on non-conformant architectures.
459467

460-
// After promotion, types will either be int, unsigned int, or the same
461-
// Maybe we express this type as promoted<T>
462-
// And then for combined
463-
// a + b
464-
// and other arithmetic expressions, the
465-
// result could be a separate type like usual_arithmetic<promoted<ushort>,
466-
// promoted<char>>
467-
// I think we just need to be careful of the sign from promoted unsigned shorts.
468+
let promoted_type = match &inner.ty.kind {
469+
TypeKind::Boolean => {
470+
Some(TypeKind::CInteger(CInteger::Int, Some(IntegerSign::Signed)))
471+
}
472+
TypeKind::Integer(bits, sign) => {
473+
if bits.bits() < BitUnits::of(32) {
474+
Some(TypeKind::CInteger(CInteger::Int, Some(IntegerSign::Signed)))
475+
} else if bits.bits() == BitUnits::of(32) {
476+
Some(TypeKind::CInteger(CInteger::Int, Some(*sign)))
477+
} else {
478+
None
479+
}
480+
}
481+
TypeKind::CInteger(c_integer, _) => match c_integer {
482+
CInteger::Char | CInteger::Short => {
483+
Some(TypeKind::CInteger(CInteger::Int, Some(IntegerSign::Signed)))
484+
}
485+
CInteger::Int | CInteger::Long | CInteger::LongLong => None,
486+
},
487+
TypeKind::SizeInteger(_) => {
488+
// We will treat size integers as if they don't get promoted
489+
None
490+
}
491+
TypeKind::IntegerLiteral(_) => {
492+
panic!("Cannot integer promote untyped integer literal. This should never happen since untyped integer literals do not exist in C.")
493+
}
494+
_ => None,
495+
};
496+
497+
if let Some(promoted_type) = promoted_type {
498+
let promoted_type = promoted_type.at(ast_expr.source);
499+
500+
return Ok(TypedExpr::new(
501+
promoted_type.clone(),
502+
ExprKind::IntegerCast(Box::new(CastFrom {
503+
cast: Cast {
504+
target_type: promoted_type,
505+
value: inner.expr,
506+
},
507+
from_type: inner.ty,
508+
}))
509+
.at(ast_expr.source),
510+
));
511+
}
468512

469-
Ok(todo!("integer promote expression - {:?}", rank))
470-
// Ok(TypedExpr::new())
513+
return Ok(inner);
471514
}
472515
}?;
473516

0 commit comments

Comments
 (0)