Skip to content

Commit 65272ab

Browse files
committed
transpile: Split off c_ast/c_stmt.rs module
1 parent 38dd187 commit 65272ab

2 files changed

Lines changed: 162 additions & 152 deletions

File tree

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
use super::{Attribute, CDeclId, CExprId, ConstIntExpr, Located, TypedAstContext};
2+
use std::fmt::Debug;
3+
use std::ops::Index;
4+
5+
#[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Copy, Clone)]
6+
pub struct CStmtId(pub u64);
7+
8+
// These are references into particular variants of AST nodes
9+
pub type CLabelId = CStmtId; // Labels point into the 'StmtKind::Label' that declared the label
10+
11+
/// Represents a statement in C (6.8 Statements)
12+
///
13+
/// Reflects the types in <http://clang.llvm.org/doxygen/classclang_1_1Stmt.html>
14+
#[derive(Debug, Clone)]
15+
pub enum CStmtKind {
16+
// Labeled statements (6.8.1)
17+
//
18+
// All of these have a `CStmtId` to represent the substatement that comes after them
19+
Label(CStmtId),
20+
Case(CExprId, CStmtId, ConstIntExpr),
21+
Default(CStmtId),
22+
23+
// Compound statements (6.8.2)
24+
Compound(Vec<CStmtId>),
25+
26+
// Expression and null statements (6.8.3)
27+
Expr(CExprId),
28+
Empty,
29+
30+
// Selection statements (6.8.4)
31+
If {
32+
scrutinee: CExprId,
33+
true_variant: CStmtId,
34+
false_variant: Option<CStmtId>,
35+
},
36+
Switch {
37+
scrutinee: CExprId,
38+
body: CStmtId,
39+
},
40+
41+
// Iteration statements (6.8.5)
42+
While {
43+
condition: CExprId,
44+
body: CStmtId,
45+
},
46+
DoWhile {
47+
body: CStmtId,
48+
condition: CExprId,
49+
},
50+
ForLoop {
51+
init: Option<CStmtId>,
52+
condition: Option<CExprId>,
53+
increment: Option<CExprId>,
54+
body: CStmtId,
55+
},
56+
57+
// Jump statements (6.8.6)
58+
Goto(CLabelId),
59+
Break,
60+
Continue,
61+
Return(Option<CExprId>),
62+
63+
// Declarations (variables, etc.)
64+
Decls(Vec<CDeclId>),
65+
66+
// GCC inline assembly
67+
Asm {
68+
asm: String,
69+
inputs: Vec<AsmOperand>,
70+
outputs: Vec<AsmOperand>,
71+
clobbers: Vec<String>,
72+
is_volatile: bool,
73+
},
74+
75+
// Statements annotated with attributes. The substatement can be a NULL
76+
// statement in case of __attribute__((__fallthrough__)) at the end of a
77+
// case statement
78+
Attributed {
79+
attributes: Vec<Attribute>,
80+
substatement: CStmtId,
81+
},
82+
}
83+
84+
pub type CStmt = Located<CStmtKind>;
85+
86+
#[derive(Clone, Debug)]
87+
pub struct AsmOperand {
88+
pub constraints: String,
89+
pub expression: CExprId,
90+
}
91+
92+
impl TypedAstContext {
93+
pub fn is_const_stmt(&self, stmt: CStmtId) -> bool {
94+
let is_const = |stmt| self.is_const_stmt(stmt);
95+
let is_const_expr = |expr| self.is_const_expr(expr);
96+
97+
use CStmtKind::*;
98+
match self[stmt].kind {
99+
Case(expr, stmt, _const_expr) => is_const_expr(expr) && is_const(stmt),
100+
Default(stmt) => is_const(stmt),
101+
Compound(ref stmts) => stmts.iter().copied().all(is_const),
102+
Expr(expr) => is_const_expr(expr),
103+
Empty => true,
104+
If {
105+
scrutinee,
106+
true_variant,
107+
false_variant,
108+
} => {
109+
is_const_expr(scrutinee)
110+
&& is_const(true_variant)
111+
&& false_variant.map_or(true, is_const)
112+
}
113+
Switch { scrutinee, body } => is_const_expr(scrutinee) && is_const(body),
114+
While { condition, body } => is_const_expr(condition) && is_const(body),
115+
DoWhile { body, condition } => is_const(body) && is_const_expr(condition),
116+
ForLoop {
117+
init,
118+
condition,
119+
increment,
120+
body,
121+
} => {
122+
init.map_or(true, is_const)
123+
&& condition.map_or(true, is_const_expr)
124+
&& increment.map_or(true, is_const_expr)
125+
&& is_const(body)
126+
}
127+
Break => true,
128+
Continue => true,
129+
Return(expr) => expr.map_or(true, is_const_expr),
130+
Decls(ref _decls) => true,
131+
Asm { .. } => false,
132+
Attributed {
133+
attributes: _,
134+
substatement,
135+
} => is_const(substatement),
136+
// `goto`s are tricky, because they can be non-local
137+
// and jump out of the context of the macro.
138+
// A `goto` and its labels are `const` if the whole state machine
139+
// we compile to has all `const` statements,
140+
// but determining what that is exactly is trickier,
141+
// and might depend on the context in which the macro is used.
142+
// This is probably fairly uncommon, so we just assume it's not `const` for now.
143+
// Note that in C, labels are for `goto`s.
144+
// There are no labeled `break`s and `continue`s.
145+
Label(_stmt) => false,
146+
Goto(_label) => false,
147+
}
148+
}
149+
}
150+
151+
impl Index<CStmtId> for TypedAstContext {
152+
type Output = CStmt;
153+
154+
fn index(&self, index: CStmtId) -> &CStmt {
155+
match self.c_stmts.get(&index) {
156+
None => panic!("Could not find {:?} in TypedAstContext", index),
157+
Some(ty) => ty,
158+
}
159+
}
160+
}

c2rust-transpile/src/c_ast/mod.rs

Lines changed: 2 additions & 152 deletions
Original file line numberDiff line numberDiff line change
@@ -15,22 +15,20 @@ pub use self::print::Printer;
1515
pub use c2rust_ast_exporter::clang_ast::{BuiltinVaListKind, SrcFile, SrcLoc, SrcSpan};
1616

1717
mod c_expr;
18+
mod c_stmt;
1819
mod c_type;
1920
mod conversion;
2021
pub mod iterators;
2122
mod print;
2223

2324
pub use c_expr::*;
25+
pub use c_stmt::*;
2426
pub use c_type::*;
2527

2628
#[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Copy, Clone)]
2729
pub struct CDeclId(pub u64);
2830

29-
#[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Copy, Clone)]
30-
pub struct CStmtId(pub u64);
31-
3231
// These are references into particular variants of AST nodes
33-
pub type CLabelId = CStmtId; // Labels point into the 'StmtKind::Label' that declared the label
3432
pub type CFieldId = CDeclId; // Records always contain 'DeclKind::Field's
3533
pub type CParamId = CDeclId; // Parameters always contain 'DeclKind::Variable's
3634
pub type CRecordId = CDeclId; // Record types need to point to 'DeclKind::Record'
@@ -479,63 +477,6 @@ impl TypedAstContext {
479477
panic!("expected a CDeclKind::Function, but passed {func_decl:?}")
480478
}
481479

482-
pub fn is_const_stmt(&self, stmt: CStmtId) -> bool {
483-
let is_const = |stmt| self.is_const_stmt(stmt);
484-
let is_const_expr = |expr| self.is_const_expr(expr);
485-
486-
use CStmtKind::*;
487-
match self[stmt].kind {
488-
Case(expr, stmt, _const_expr) => is_const_expr(expr) && is_const(stmt),
489-
Default(stmt) => is_const(stmt),
490-
Compound(ref stmts) => stmts.iter().copied().all(is_const),
491-
Expr(expr) => is_const_expr(expr),
492-
Empty => true,
493-
If {
494-
scrutinee,
495-
true_variant,
496-
false_variant,
497-
} => {
498-
is_const_expr(scrutinee)
499-
&& is_const(true_variant)
500-
&& false_variant.map_or(true, is_const)
501-
}
502-
Switch { scrutinee, body } => is_const_expr(scrutinee) && is_const(body),
503-
While { condition, body } => is_const_expr(condition) && is_const(body),
504-
DoWhile { body, condition } => is_const(body) && is_const_expr(condition),
505-
ForLoop {
506-
init,
507-
condition,
508-
increment,
509-
body,
510-
} => {
511-
init.map_or(true, is_const)
512-
&& condition.map_or(true, is_const_expr)
513-
&& increment.map_or(true, is_const_expr)
514-
&& is_const(body)
515-
}
516-
Break => true,
517-
Continue => true,
518-
Return(expr) => expr.map_or(true, is_const_expr),
519-
Decls(ref _decls) => true,
520-
Asm { .. } => false,
521-
Attributed {
522-
attributes: _,
523-
substatement,
524-
} => is_const(substatement),
525-
// `goto`s are tricky, because they can be non-local
526-
// and jump out of the context of the macro.
527-
// A `goto` and its labels are `const` if the whole state machine
528-
// we compile to has all `const` statements,
529-
// but determining what that is exactly is trickier,
530-
// and might depend on the context in which the macro is used.
531-
// This is probably fairly uncommon, so we just assume it's not `const` for now.
532-
// Note that in C, labels are for `goto`s.
533-
// There are no labeled `break`s and `continue`s.
534-
Label(_stmt) => false,
535-
Goto(_label) => false,
536-
}
537-
}
538-
539480
pub fn prune_unwanted_decls(&mut self, want_unused_functions: bool) {
540481
// Starting from a set of root declarations, walk each one to find declarations it
541482
// depends on. Then walk each of those, recursively.
@@ -815,20 +756,8 @@ impl Index<CDeclId> for TypedAstContext {
815756
}
816757
}
817758

818-
impl Index<CStmtId> for TypedAstContext {
819-
type Output = CStmt;
820-
821-
fn index(&self, index: CStmtId) -> &CStmt {
822-
match self.c_stmts.get(&index) {
823-
None => panic!("Could not find {:?} in TypedAstContext", index),
824-
Some(ty) => ty,
825-
}
826-
}
827-
}
828-
829759
/// All of our AST types should have location information bundled with them
830760
pub type CDecl = Located<CDeclKind>;
831-
pub type CStmt = Located<CStmtKind>;
832761

833762
#[derive(Debug, Clone)]
834763
pub enum CDeclKind {
@@ -943,85 +872,6 @@ impl CDeclKind {
943872
}
944873
}
945874

946-
/// Represents a statement in C (6.8 Statements)
947-
///
948-
/// Reflects the types in <http://clang.llvm.org/doxygen/classclang_1_1Stmt.html>
949-
#[derive(Debug, Clone)]
950-
pub enum CStmtKind {
951-
// Labeled statements (6.8.1)
952-
//
953-
// All of these have a `CStmtId` to represent the substatement that comes after them
954-
Label(CStmtId),
955-
Case(CExprId, CStmtId, ConstIntExpr),
956-
Default(CStmtId),
957-
958-
// Compound statements (6.8.2)
959-
Compound(Vec<CStmtId>),
960-
961-
// Expression and null statements (6.8.3)
962-
Expr(CExprId),
963-
Empty,
964-
965-
// Selection statements (6.8.4)
966-
If {
967-
scrutinee: CExprId,
968-
true_variant: CStmtId,
969-
false_variant: Option<CStmtId>,
970-
},
971-
Switch {
972-
scrutinee: CExprId,
973-
body: CStmtId,
974-
},
975-
976-
// Iteration statements (6.8.5)
977-
While {
978-
condition: CExprId,
979-
body: CStmtId,
980-
},
981-
DoWhile {
982-
body: CStmtId,
983-
condition: CExprId,
984-
},
985-
ForLoop {
986-
init: Option<CStmtId>,
987-
condition: Option<CExprId>,
988-
increment: Option<CExprId>,
989-
body: CStmtId,
990-
},
991-
992-
// Jump statements (6.8.6)
993-
Goto(CLabelId),
994-
Break,
995-
Continue,
996-
Return(Option<CExprId>),
997-
998-
// Declarations (variables, etc.)
999-
Decls(Vec<CDeclId>),
1000-
1001-
// GCC inline assembly
1002-
Asm {
1003-
asm: String,
1004-
inputs: Vec<AsmOperand>,
1005-
outputs: Vec<AsmOperand>,
1006-
clobbers: Vec<String>,
1007-
is_volatile: bool,
1008-
},
1009-
1010-
// Statements annotated with attributes. The substatement can be a NULL
1011-
// statement in case of __attribute__((__fallthrough__)) at the end of a
1012-
// case statement
1013-
Attributed {
1014-
attributes: Vec<Attribute>,
1015-
substatement: CStmtId,
1016-
},
1017-
}
1018-
1019-
#[derive(Clone, Debug)]
1020-
pub struct AsmOperand {
1021-
pub constraints: String,
1022-
pub expression: CExprId,
1023-
}
1024-
1025875
/// Enumeration of supported attributes for Declarations
1026876
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
1027877
pub enum Attribute {

0 commit comments

Comments
 (0)