Skip to content

Commit 404a700

Browse files
committed
Added ability to assume that int is at least 32 bits
1 parent 5bf9d7e commit 404a700

27 files changed

+246
-94
lines changed

Diff for: src/ast/conforming.rs

+18-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,22 @@
1+
use super::CIntegerAssumptions;
2+
13
#[derive(Copy, Clone, Debug)]
2-
pub enum ConformBehavior {
4+
pub enum Language {
35
Adept,
46
C,
57
}
8+
9+
#[derive(Copy, Clone, Debug)]
10+
pub enum ConformBehavior {
11+
Adept(CIntegerAssumptions),
12+
C,
13+
}
14+
15+
impl ConformBehavior {
16+
pub fn c_integer_assumptions(&self) -> CIntegerAssumptions {
17+
match self {
18+
ConformBehavior::Adept(assumptions) => *assumptions,
19+
ConformBehavior::C => Default::default(),
20+
}
21+
}
22+
}

Diff for: src/ast/datatype/c_integer.rs

+29-5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use super::description::{IntegerBits, IntegerSign};
2-
use crate::{data_units::ByteUnits, target::Target};
2+
use crate::{ast::Settings, data_units::ByteUnits, target::Target};
33
use derive_more::IsVariant;
44

55
#[derive(Copy, Clone, Debug, PartialEq, Eq, IsVariant, PartialOrd, Ord)]
@@ -20,10 +20,17 @@ impl CInteger {
2020
}
2121
}
2222

23-
pub fn min_bits(self) -> IntegerBits {
23+
pub fn min_bits(self, assumptions: CIntegerAssumptions) -> IntegerBits {
2424
match self {
2525
Self::Char => IntegerBits::Bits8,
26-
Self::Short | Self::Int => IntegerBits::Bits16,
26+
Self::Short => IntegerBits::Bits16,
27+
Self::Int => {
28+
if assumptions.int_at_least_32_bits {
29+
IntegerBits::Bits32
30+
} else {
31+
IntegerBits::Bits16
32+
}
33+
}
2734
Self::Long => IntegerBits::Bits32,
2835
Self::LongLong => IntegerBits::Bits64,
2936
}
@@ -39,11 +46,15 @@ impl CInteger {
3946
}
4047
}
4148

42-
pub fn smallest_that_fits(min_c_integer: Self, bits: IntegerBits) -> Option<Self> {
49+
pub fn smallest_that_fits(
50+
min_c_integer: Self,
51+
bits: IntegerBits,
52+
assumptions: CIntegerAssumptions,
53+
) -> Option<Self> {
4354
let mut possible = min_c_integer;
4455

4556
loop {
46-
if possible.min_bits() >= bits {
57+
if possible.min_bits(assumptions) >= bits {
4758
return Some(possible);
4859
}
4960

@@ -91,3 +102,16 @@ pub fn fmt_c_integer(
91102

92103
Ok(())
93104
}
105+
106+
#[derive(Copy, Clone, Debug, Default)]
107+
pub struct CIntegerAssumptions {
108+
pub int_at_least_32_bits: bool,
109+
}
110+
111+
impl CIntegerAssumptions {
112+
pub fn new(settings: &Settings) -> Self {
113+
Self {
114+
int_at_least_32_bits: settings.assume_int_at_least_32_bits,
115+
}
116+
}
117+
}

Diff for: src/ast/expr/structure_literal.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
use super::Expr;
2-
use crate::ast::{ConformBehavior, Type};
2+
use crate::ast::{Language, Type};
33

44
#[derive(Clone, Debug)]
55
pub struct StructureLiteral {
66
pub ast_type: Type,
77
pub fields: Vec<FieldInitializer>,
88
pub fill_behavior: FillBehavior,
9-
pub conform_behavior: ConformBehavior,
9+
pub language: Language,
1010
}
1111

1212
#[derive(Clone, Debug)]

Diff for: src/ast/workspace/mod.rs

+12-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use super::AstFile;
1+
use super::{AstFile, CIntegerAssumptions};
22
use crate::{
33
iter_ext::MapSecond,
44
source_files::SourceFiles,
@@ -55,6 +55,7 @@ impl<'a> AstWorkspace<'a> {
5555
adept_version: AdeptVersion::CURRENT,
5656
debug_skip_merging_helper_exprs: false,
5757
imported_namespaces: vec![],
58+
assume_int_at_least_32_bits: false,
5859
}),
5960
Self::DEFAULT_SETTINGS_ID.0
6061
);
@@ -116,9 +117,18 @@ pub struct Settings {
116117
pub adept_version: AdeptVersion,
117118
pub debug_skip_merging_helper_exprs: bool,
118119
pub imported_namespaces: Vec<Box<str>>,
120+
pub assume_int_at_least_32_bits: bool,
119121
}
120122

121-
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
123+
impl Settings {
124+
pub fn c_integer_assumptions(&self) -> CIntegerAssumptions {
125+
CIntegerAssumptions {
126+
int_at_least_32_bits: self.assume_int_at_least_32_bits,
127+
}
128+
}
129+
}
130+
131+
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord)]
122132
pub struct SettingsId(pub usize);
123133

124134
struct ConfigureJob {

Diff for: src/c/translation/expr/compound_literal.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::{
2-
ast::{self, AstFile, ConformBehavior, FillBehavior},
2+
ast::{self, AstFile, FillBehavior, Language},
33
c::{
44
parser::{
55
expr::{CompoundLiteral, Initializer},
@@ -47,7 +47,7 @@ pub fn translate_compound_literal(
4747
ast_type,
4848
fields,
4949
fill_behavior: FillBehavior::Zeroed,
50-
conform_behavior: ConformBehavior::C,
50+
language: Language::C,
5151
}))
5252
.at(source),
5353
)

Diff for: src/interpreter/syscall_handler.rs

+6
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ pub struct BuildSystemSyscallHandler {
3636
pub link_frameworks: HashSet<String>,
3737
pub debug_skip_merging_helper_exprs: bool,
3838
pub imported_namespaces: Vec<Box<str>>,
39+
pub assume_int_at_least_32_bits: bool,
3940
}
4041

4142
fn read_cstring(memory: &Memory, value: &Value) -> String {
@@ -124,6 +125,11 @@ impl SyscallHandler for BuildSystemSyscallHandler {
124125
.push(read_cstring(memory, &args[0]).into_boxed_str());
125126
Value::Literal(ir::Literal::Void)
126127
}
128+
ir::InterpreterSyscallKind::AssumeIntAtLeast32Bits => {
129+
assert_eq!(args.len(), 0);
130+
self.assume_int_at_least_32_bits = true;
131+
Value::Literal(ir::Literal::Void)
132+
}
127133
}
128134
}
129135
}

Diff for: src/interpreter_env/mod.rs

+33
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,34 @@ use crate::{
1515
};
1616
use indexmap::IndexMap;
1717

18+
fn thin_void_function(name: impl ToString, syscall_kind: InterpreterSyscallKind) -> Function {
19+
let source = Source::internal();
20+
let void = TypeKind::Void.at(Source::internal());
21+
22+
Function {
23+
name: name.to_string(),
24+
parameters: Parameters {
25+
required: vec![],
26+
is_cstyle_vararg: false,
27+
},
28+
return_type: void.clone(),
29+
stmts: vec![StmtKind::Expr(
30+
ExprKind::InterpreterSyscall(Box::new(InterpreterSyscall {
31+
kind: syscall_kind,
32+
args: vec![],
33+
result_type: void.clone(),
34+
}))
35+
.at(source),
36+
)
37+
.at(source)],
38+
abide_abi: false,
39+
is_foreign: false,
40+
source,
41+
tag: None,
42+
namespace: None,
43+
}
44+
}
45+
1846
fn thin_cstring_function(
1947
name: impl ToString,
2048
param_name: impl ToString,
@@ -151,6 +179,11 @@ pub fn setup_build_system_interpreter_symbols(file: &mut AstFile) {
151179
InterpreterSyscallKind::ImportNamespace,
152180
));
153181

182+
file.functions.push(thin_void_function(
183+
"assumeIntAtLeast32Bits",
184+
InterpreterSyscallKind::AssumeIntAtLeast32Bits,
185+
));
186+
154187
file.functions.push(Function {
155188
name: "project".into(),
156189
parameters: Parameters {

Diff for: src/ir/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@ pub enum InterpreterSyscallKind {
146146
BuildLinkFrameworkName,
147147
Experimental,
148148
ImportNamespace,
149+
AssumeIntAtLeast32Bits,
149150
}
150151

151152
#[derive(Clone, Debug)]

Diff for: src/parser/parse_expr/primary/structure_literal.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
use super::Parser;
22
use crate::{
3-
ast::{
4-
ConformBehavior, Expr, ExprKind, FieldInitializer, FillBehavior, StructureLiteral, Type,
5-
},
3+
ast::{Expr, ExprKind, FieldInitializer, FillBehavior, Language, StructureLiteral, Type},
64
inflow::Inflow,
75
parser::error::ParseError,
86
token::{Token, TokenKind},
@@ -68,7 +66,7 @@ impl<'a, I: Inflow<Token>> Parser<'a, I> {
6866
ast_type,
6967
fields,
7068
fill_behavior,
71-
conform_behavior: ConformBehavior::Adept,
69+
language: Language::Adept,
7270
})),
7371
source,
7472
))

Diff for: src/pragma_section/run.rs

+1
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ impl PragmaSection {
111111
adept_version,
112112
debug_skip_merging_helper_exprs: user_settings.debug_skip_merging_helper_exprs,
113113
imported_namespaces: user_settings.imported_namespaces,
114+
assume_int_at_least_32_bits: user_settings.assume_int_at_least_32_bits,
114115
})
115116
}
116117
}

Diff for: src/resolve/conform/from_integer.rs

+8-5
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ pub fn from_integer(
1616
) -> Option<TypedExpr> {
1717
match &to_type.kind {
1818
TypeKind::Integer(to_bits, to_sign) => match behavior {
19-
ConformBehavior::Adept => from_integer_adept_mode(
19+
ConformBehavior::Adept(_) => from_integer_adept_mode(
2020
&expr.expr,
2121
from_bits,
2222
from_sign,
@@ -37,6 +37,7 @@ pub fn from_integer(
3737
TypeKind::CInteger(to_c_integer, to_sign) => conform_from_integer_to_c_integer(
3838
expr,
3939
mode,
40+
behavior,
4041
from_bits,
4142
from_sign,
4243
*to_c_integer,
@@ -85,22 +86,24 @@ fn from_integer_c_mode(
8586

8687
fn conform_from_integer_to_c_integer(
8788
expr: &TypedExpr,
88-
conform_mode: ConformMode,
89+
mode: ConformMode,
90+
behavior: ConformBehavior,
8991
from_bits: IntegerBits,
9092
from_sign: IntegerSign,
9193
to_c_integer: CInteger,
9294
to_sign: Option<IntegerSign>,
9395
source: Source,
9496
) -> Option<TypedExpr> {
9597
let target_type = TypeKind::CInteger(to_c_integer, to_sign).at(source);
98+
let assumptions = behavior.c_integer_assumptions();
9699

97100
let is_lossless = match to_sign {
98-
Some(to_sign) if from_sign == to_sign => from_bits <= to_c_integer.min_bits(),
99-
Some(to_sign) if to_sign.is_signed() => from_bits < to_c_integer.min_bits(),
101+
Some(to_sign) if from_sign == to_sign => from_bits <= to_c_integer.min_bits(assumptions),
102+
Some(to_sign) if to_sign.is_signed() => from_bits < to_c_integer.min_bits(assumptions),
100103
_ => false,
101104
};
102105

103-
if conform_mode.allow_lossy_integer() || is_lossless {
106+
if mode.allow_lossy_integer() || is_lossless {
104107
let cast_from = CastFrom {
105108
cast: Cast::new(target_type.clone(), expr.expr.clone()),
106109
from_type: expr.resolved_type.clone(),

Diff for: src/resolve/conform/from_integer_literal.rs

+10-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::{
2-
ast::{CInteger, FloatSize, IntegerBits, IntegerKnown, IntegerRigidity},
2+
ast::{CInteger, CIntegerAssumptions, FloatSize, IntegerBits, IntegerKnown, IntegerRigidity},
33
data_units::BitUnits,
44
ir::IntegerSign,
55
resolved::{Expr, ExprKind, Type, TypeKind, TypedExpr},
@@ -8,11 +8,16 @@ use crate::{
88
use num::{BigInt, Zero};
99
use num_traits::ToPrimitive;
1010

11-
pub fn from_integer_literal(value: &BigInt, source: Source, to_type: &Type) -> Option<TypedExpr> {
11+
pub fn from_integer_literal(
12+
value: &BigInt,
13+
assumptions: CIntegerAssumptions,
14+
source: Source,
15+
to_type: &Type,
16+
) -> Option<TypedExpr> {
1217
match &to_type.kind {
1318
TypeKind::Floating(to_size) => from_integer_literal_to_float(value, *to_size, source),
1419
TypeKind::CInteger(to_c_integer, to_sign) => {
15-
from_integer_literal_to_c_integer(value, *to_c_integer, *to_sign, source)
20+
from_integer_literal_to_c_integer(value, *to_c_integer, *to_sign, assumptions, source)
1621
}
1722
TypeKind::Integer(to_bits, to_sign) => {
1823
from_integer_literal_to_integer(value, *to_bits, *to_sign, source)
@@ -55,12 +60,13 @@ fn from_integer_literal_to_c_integer(
5560
value: &BigInt,
5661
to_c_integer: CInteger,
5762
to_sign: Option<IntegerSign>,
63+
assumptions: CIntegerAssumptions,
5864
source: Source,
5965
) -> Option<TypedExpr> {
6066
let needs_bits =
6167
BitUnits::of(value.bits() + (*value < BigInt::zero()).then_some(1).unwrap_or(0));
6268

63-
(needs_bits <= to_c_integer.min_bits().bits()).then(|| {
69+
(needs_bits <= to_c_integer.min_bits(assumptions).bits()).then(|| {
6470
TypedExpr::new(
6571
TypeKind::CInteger(to_c_integer, to_sign).at(source),
6672
ExprKind::IntegerKnown(Box::new(IntegerKnown {

Diff for: src/resolve/conform/mod.rs

+8-8
Original file line numberDiff line numberDiff line change
@@ -24,23 +24,23 @@ pub fn conform_expr(
2424
expr: &TypedExpr,
2525
to_type: &Type,
2626
mode: ConformMode,
27-
conform_behavior: ConformBehavior,
27+
behavior: ConformBehavior,
2828
conform_source: Source,
2929
) -> Option<TypedExpr> {
3030
if expr.resolved_type == *to_type {
3131
return Some(expr.clone());
3232
}
3333

3434
match &expr.resolved_type.kind {
35-
TypeKind::IntegerLiteral(from) => from_integer_literal(from, expr.expr.source, to_type),
36-
TypeKind::Integer(from_bits, from_sign) => from_integer(
37-
expr,
38-
mode,
39-
conform_behavior,
40-
*from_bits,
41-
*from_sign,
35+
TypeKind::IntegerLiteral(from) => from_integer_literal(
36+
from,
37+
behavior.c_integer_assumptions(),
38+
expr.expr.source,
4239
to_type,
4340
),
41+
TypeKind::Integer(from_bits, from_sign) => {
42+
from_integer(expr, mode, behavior, *from_bits, *from_sign, to_type)
43+
}
4444
TypeKind::FloatLiteral(from) => from_float_literal(*from, to_type, conform_source),
4545
TypeKind::Floating(from_size) => from_float(expr, *from_size, to_type),
4646
TypeKind::Pointer(from_inner) => from_pointer(expr, mode, from_inner, to_type),

0 commit comments

Comments
 (0)