Skip to content

Commit a3bff0f

Browse files
committed
WIP: Handle some C11 atomic types and operations
1 parent 789a8bd commit a3bff0f

File tree

6 files changed

+85
-10
lines changed

6 files changed

+85
-10
lines changed

c2rust-transpile/src/c_ast/conversion.rs

+13-2
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,8 @@ fn parse_cast_kind(kind: &str) -> CastKind {
162162
"BuiltinFnToFnPtr" => CastKind::BuiltinFnToFnPtr,
163163
"ConstCast" => CastKind::ConstCast,
164164
"VectorSplat" => CastKind::VectorSplat,
165+
"AtomicToNonAtomic" => CastKind::AtomicToNonAtomic,
166+
"NonAtomicToAtomic" => CastKind::NonAtomicToAtomic,
165167
k => panic!("Unsupported implicit cast: {}", k),
166168
}
167169
}
@@ -816,8 +818,12 @@ impl ConversionContext {
816818
}
817819

818820
TypeTag::TagAtomicType => {
819-
// Next step in atomics implementation: Transfer to a CTypeKind
820-
panic!("C11 Atomics are not implemented in C2Rust yet.");
821+
let qt =
822+
from_value(ty_node.extras[0].clone()).expect("Inner type not found");
823+
let qt_new = self.visit_qualified_type(qt);
824+
let atomic_ty = CTypeKind::Atomic(qt_new);
825+
self.add_type(new_id, not_located(atomic_ty));
826+
self.processed_nodes.insert(new_id, OTHER_TYPE);
821827
}
822828

823829
t => panic!(
@@ -1761,6 +1767,11 @@ impl ConversionContext {
17611767
let typ = node.type_id.expect("Expected expression to have type");
17621768
let typ = self.visit_qualified_type(typ);
17631769

1770+
// Perhaps as an optimization since atomic_init has no order,
1771+
// clang stores val1 in the position otherwise used for order
1772+
let is_atomic = name == "__c11_atomic_init" || name == "__opencl_atomic_init";
1773+
let val1 = if is_atomic { Some(order) } else { val1 };
1774+
17641775
let e = CExprKind::Atomic {
17651776
typ,
17661777
name,

c2rust-transpile/src/c_ast/iterators.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,8 @@ fn immediate_type_children(kind: &CTypeKind) -> Vec<SomeId> {
293293
| Reference(qtype)
294294
| Attributed(qtype, _)
295295
| BlockPointer(qtype)
296-
| Vector(qtype, _) => {
296+
| Vector(qtype, _)
297+
| Atomic(qtype) => {
297298
intos![qtype.ctype]
298299
}
299300

c2rust-transpile/src/c_ast/mod.rs

+5
Original file line numberDiff line numberDiff line change
@@ -1214,6 +1214,8 @@ pub enum CastKind {
12141214
BuiltinFnToFnPtr,
12151215
ConstCast,
12161216
VectorSplat,
1217+
AtomicToNonAtomic,
1218+
NonAtomicToAtomic,
12171219
}
12181220

12191221
/// Represents a unary operator in C (6.5.3 Unary operators) and GNU C extensions
@@ -1672,6 +1674,9 @@ pub enum CTypeKind {
16721674

16731675
Half,
16741676
BFloat16,
1677+
1678+
// Atomic types (6.7.2.4)
1679+
Atomic(CQualTypeId)
16751680
}
16761681

16771682
impl CTypeKind {

c2rust-transpile/src/convert_type.rs

+1
Original file line numberDiff line numberDiff line change
@@ -380,6 +380,7 @@ impl TypeConverter {
380380
}
381381

382382
CTypeKind::Attributed(ty, _) => self.convert(ctxt, ty.ctype),
383+
CTypeKind::Atomic(ty) => self.convert(ctxt, ty.ctype),
383384

384385
// ANSI/ISO C-style function
385386
CTypeKind::Function(ret, ref params, is_var, is_noreturn, true) => {

c2rust-transpile/src/translator/atomics.rs

+61-6
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,22 @@ impl<'c> Translation<'c> {
1616
let memorder = &self.ast_context[expr];
1717
let i = match memorder.kind {
1818
CExprKind::Literal(_, CLiteral::Integer(i, _)) => Some(i),
19+
CExprKind::DeclRef(_, decl_id, LRValue::RValue) => {
20+
let decl = self
21+
.ast_context
22+
.get_decl(&decl_id)
23+
.unwrap();
24+
match decl.kind {
25+
CDeclKind::EnumConstant { name: _, value: v} => match v {
26+
ConstIntExpr::I(i) => {
27+
assert!(0 <= i);
28+
Some(i as u64)
29+
},
30+
ConstIntExpr::U(u) => Some(u),
31+
}
32+
_ => unimplemented!()
33+
}
34+
},
1935
_ => None,
2036
}?;
2137
use Ordering::*;
@@ -76,7 +92,8 @@ impl<'c> Translation<'c> {
7692
}
7793

7894
match name {
79-
"__atomic_load" | "__atomic_load_n" => ptr.and_then(|ptr| {
95+
"__atomic_load" | "__atomic_load_n" | "__c11_atomic_load"
96+
=> ptr.and_then(|ptr| {
8097
let intrinsic_name = format!("atomic_load_{}", order_name(static_order(order)));
8198

8299
self.use_feature("core_intrinsics");
@@ -105,7 +122,9 @@ impl<'c> Translation<'c> {
105122
}
106123
}),
107124

108-
"__atomic_store" | "__atomic_store_n" => {
125+
"__atomic_store"
126+
| "__atomic_store_n"
127+
| "__c11_atomic_store" => {
109128
let val = val1.expect("__atomic_store must have a val argument");
110129
ptr.and_then(|ptr| {
111130
val.and_then(|val| {
@@ -131,7 +150,28 @@ impl<'c> Translation<'c> {
131150
})
132151
}
133152

134-
"__atomic_exchange" | "__atomic_exchange_n" => {
153+
// NOTE: there is no corresponding __atomic_init builtin in clang
154+
"__c11_atomic_init" => {
155+
let val = val1.expect(
156+
&format!("__atomic_init must have a val argument"));
157+
ptr.and_then(|ptr| {
158+
val.and_then(|val| {
159+
let assignment = mk().assign_expr(
160+
mk().unary_expr(UnOp::Deref(Default::default()), ptr),
161+
val,
162+
);
163+
self.convert_side_effects_expr(
164+
ctx,
165+
WithStmts::new_val(assignment),
166+
"Builtin is not supposed to be used",
167+
)
168+
})
169+
})
170+
},
171+
172+
"__atomic_exchange"
173+
| "__atomic_exchange_n"
174+
| "__c11_atomic_exchange" => {
135175
let val = val1.expect("__atomic_store must have a val argument");
136176
ptr.and_then(|ptr| {
137177
val.and_then(|val| {
@@ -176,10 +216,19 @@ impl<'c> Translation<'c> {
176216
})
177217
}
178218

179-
"__atomic_compare_exchange" | "__atomic_compare_exchange_n" => {
219+
"__atomic_compare_exchange"
220+
| "__atomic_compare_exchange_n"
221+
| "__c11_atomic_compare_exchange_strong" => {
180222
let expected =
181223
val1.expect("__atomic_compare_exchange must have a expected argument");
182224
let desired = val2.expect("__atomic_compare_exchange must have a desired argument");
225+
// Some C11 atomic operations encode the weak property in the name
226+
let weak = match (name, weak) {
227+
("__c11_atomic_compare_exchange_strong", None) => Some(false),
228+
("__c11_atomic_compare_exchange_weak", None) => Some(true),
229+
_ => weak
230+
};
231+
183232
ptr.and_then(|ptr| {
184233
expected.and_then(|expected| {
185234
desired.and_then(|desired| {
@@ -258,7 +307,13 @@ impl<'c> Translation<'c> {
258307
| "__atomic_fetch_and"
259308
| "__atomic_fetch_xor"
260309
| "__atomic_fetch_or"
261-
| "__atomic_fetch_nand" => {
310+
| "__atomic_fetch_nand"
311+
| "__c11_atomic_fetch_add"
312+
| "__c11_atomic_fetch_sub"
313+
| "__c11_atomic_fetch_and"
314+
| "__c11_atomic_fetch_xor"
315+
| "__c11_atomic_fetch_or"
316+
| "__c11_atomic_fetch_nand" => {
262317
let intrinsic_name = if name.contains("_add") {
263318
"atomic_xadd"
264319
} else if name.contains("_sub") {
@@ -285,7 +340,7 @@ impl<'c> Translation<'c> {
285340
})
286341
}
287342

288-
_ => unimplemented!("atomic not implemented"),
343+
_ => unimplemented!("atomic not implemented: {}", name),
289344
}
290345
}
291346

c2rust-transpile/src/translator/mod.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -4412,6 +4412,8 @@ impl<'c> Translation<'c> {
44124412
CastKind::VectorSplat => Err(TranslationError::generic(
44134413
"TODO vector splat casts not supported",
44144414
)),
4415+
4416+
CastKind::AtomicToNonAtomic | CastKind::NonAtomicToAtomic => Ok(val),
44154417
}
44164418
}
44174419

@@ -4920,7 +4922,7 @@ impl<'c> Translation<'c> {
49204922
Vector(..) => {
49214923
// Handled in `import_simd_typedef`
49224924
}
4923-
TypeOfExpr(_) | BuiltinFn => {}
4925+
TypeOfExpr(_) | BuiltinFn | Atomic(..) => {}
49244926
}
49254927
}
49264928

0 commit comments

Comments
 (0)