Skip to content

Commit 0b9db95

Browse files
committed
2 parents 85554d2 + 042845b commit 0b9db95

File tree

8 files changed

+97
-39
lines changed

8 files changed

+97
-39
lines changed

c2rust-ast-exporter/src/AstExporter.cpp

+13-30
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,8 @@ class TypeEncoder final : public TypeVisitor<TypeEncoder> {
281281

282282
void VisitVariableArrayType(const VariableArrayType *T);
283283

284+
void VisitAtomicType(const AtomicType *AT);
285+
284286
void VisitIncompleteArrayType(const IncompleteArrayType *T) {
285287
auto t = T->getElementType();
286288
auto qt = encodeQualType(t);
@@ -1960,10 +1962,6 @@ class TranslateASTVisitor final
19601962
// Use the type from the definition in case the extern was an incomplete
19611963
// type
19621964
auto T = def->getType();
1963-
if (isa<AtomicType>(T)) {
1964-
printC11AtomicError(def);
1965-
abort();
1966-
}
19671965

19681966
auto loc = is_defn ? def->getLocation() : VD->getLocation();
19691967

@@ -2048,10 +2046,6 @@ class TranslateASTVisitor final
20482046
auto byteSize = 0;
20492047

20502048
auto t = D->getTypeForDecl();
2051-
if (isa<AtomicType>(t)) {
2052-
printC11AtomicError(D);
2053-
abort();
2054-
}
20552049

20562050
auto loc = D->getLocation();
20572051
std::vector<void *> childIds;
@@ -2126,10 +2120,6 @@ class TranslateASTVisitor final
21262120
// exit early via code like `if (!D->isCompleteDefinition()) return true;`.
21272121

21282122
auto t = D->getTypeForDecl();
2129-
if (isa<AtomicType>(t)) {
2130-
printC11AtomicError(D);
2131-
abort();
2132-
}
21332123

21342124
std::vector<void *> childIds;
21352125
for (auto x : D->enumerators()) {
@@ -2189,10 +2179,6 @@ class TranslateASTVisitor final
21892179

21902180
std::vector<void *> childIds;
21912181
auto t = D->getType();
2192-
if (isa<AtomicType>(t)) {
2193-
printC11AtomicError(D);
2194-
abort();
2195-
}
21962182

21972183
auto record = D->getParent();
21982184
const ASTRecordLayout &layout =
@@ -2434,11 +2420,6 @@ class TranslateASTVisitor final
24342420
CharSourceRange::getCharRange(E->getSourceRange()));
24352421
}
24362422

2437-
void printC11AtomicError(Decl *D) {
2438-
std::string msg = "C11 Atomics are not supported. Aborting.";
2439-
printError(msg, D);
2440-
}
2441-
24422423
void printError(std::string Message, Decl *D) {
24432424
auto DiagBuilder =
24442425
getDiagBuilder(D->getLocation(), DiagnosticsEngine::Error);
@@ -2524,15 +2505,17 @@ void TypeEncoder::VisitVariableArrayType(const VariableArrayType *T) {
25242505

25252506
VisitQualType(t);
25262507
}
2527-
//
2528-
//void TypeEncoder::VisitAtomicType(const AtomicType *AT) {
2529-
// std::string msg =
2530-
// "C11 Atomic types are not supported. Aborting.";
2531-
//// auto horse = AT->get
2532-
//// astEncoder->printError(msg, AT);
2533-
// AT->getValueType()->dump();
2534-
// abort();
2535-
//}
2508+
2509+
void TypeEncoder::VisitAtomicType(const AtomicType *AT) {
2510+
auto t = AT->getValueType();
2511+
auto qt = encodeQualType(t);
2512+
2513+
encodeType(AT, TagAtomicType, [qt](CborEncoder *local) {
2514+
cbor_encode_uint(local, qt);
2515+
});
2516+
2517+
VisitQualType(t);
2518+
}
25362519

25372520
class TranslateConsumer : public clang::ASTConsumer {
25382521
Outputs *outputs;

c2rust-ast-exporter/src/ast_tags.hpp

+2
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,8 @@ enum TypeTag {
147147
TagSveBool,
148148
TagSveBoolx2,
149149
TagSveBoolx4,
150+
151+
TagAtomicType,
150152
};
151153

152154
enum StringTypeTag {

c2rust-transpile/src/c_ast/conversion.rs

+15
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
}
@@ -824,6 +826,14 @@ impl ConversionContext {
824826
self.processed_nodes.insert(new_id, OTHER_TYPE);
825827
}
826828

829+
TypeTag::TagAtomicType => {
830+
let qt = from_value(ty_node.extras[0].clone()).expect("Inner type not found");
831+
let qt_new = self.visit_qualified_type(qt);
832+
let atomic_ty = CTypeKind::Atomic(qt_new);
833+
self.add_type(new_id, not_located(atomic_ty));
834+
self.processed_nodes.insert(new_id, OTHER_TYPE);
835+
}
836+
827837
t => panic!(
828838
"Type conversion not implemented for {:?} expecting {:?}",
829839
t, expected_ty
@@ -1765,6 +1775,11 @@ impl ConversionContext {
17651775
let typ = node.type_id.expect("Expected expression to have type");
17661776
let typ = self.visit_qualified_type(typ);
17671777

1778+
// Perhaps as an optimization since atomic_init has no order,
1779+
// clang stores val1 in the position otherwise used for order
1780+
let is_atomic = name == "__c11_atomic_init" || name == "__opencl_atomic_init";
1781+
let val1 = if is_atomic { Some(order) } else { val1 };
1782+
17681783
let e = CExprKind::Atomic {
17691784
typ,
17701785
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
@@ -1223,6 +1223,8 @@ pub enum CastKind {
12231223
BuiltinFnToFnPtr,
12241224
ConstCast,
12251225
VectorSplat,
1226+
AtomicToNonAtomic,
1227+
NonAtomicToAtomic,
12261228
}
12271229

12281230
/// Represents a unary operator in C (6.5.3 Unary operators) and GNU C extensions
@@ -1685,6 +1687,9 @@ pub enum CTypeKind {
16851687
// ARM Scalable Vector Extention types
16861688
// TODO: represent all the individual types in AArch64SVEACLETypes.def
16871689
UnhandledSveType,
1690+
1691+
// Atomic types (6.7.2.4)
1692+
Atomic(CQualTypeId),
16881693
}
16891694

16901695
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

+56-7
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,19 @@ 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.ast_context.get_decl(&decl_id).unwrap();
21+
match decl.kind {
22+
CDeclKind::EnumConstant { name: _, value: v } => match v {
23+
ConstIntExpr::I(i) => {
24+
assert!(0 <= i);
25+
Some(i as u64)
26+
}
27+
ConstIntExpr::U(u) => Some(u),
28+
},
29+
_ => unimplemented!(),
30+
}
31+
}
1932
_ => None,
2033
}?;
2134
use Ordering::*;
@@ -76,7 +89,7 @@ impl<'c> Translation<'c> {
7689
}
7790

7891
match name {
79-
"__atomic_load" | "__atomic_load_n" => ptr.and_then(|ptr| {
92+
"__atomic_load" | "__atomic_load_n" | "__c11_atomic_load" => ptr.and_then(|ptr| {
8093
let intrinsic_name = format!("atomic_load_{}", order_name(static_order(order)));
8194

8295
self.use_feature("core_intrinsics");
@@ -105,7 +118,7 @@ impl<'c> Translation<'c> {
105118
}
106119
}),
107120

108-
"__atomic_store" | "__atomic_store_n" => {
121+
"__atomic_store" | "__atomic_store_n" | "__c11_atomic_store" => {
109122
let val = val1.expect("__atomic_store must have a val argument");
110123
ptr.and_then(|ptr| {
111124
val.and_then(|val| {
@@ -131,7 +144,25 @@ impl<'c> Translation<'c> {
131144
})
132145
}
133146

134-
"__atomic_exchange" | "__atomic_exchange_n" => {
147+
// NOTE: there is no corresponding __atomic_init builtin in clang
148+
"__c11_atomic_init" => {
149+
let val = val1.expect(&format!("__atomic_init must have a val argument"));
150+
ptr.and_then(|ptr| {
151+
val.and_then(|val| {
152+
let assignment = mk().assign_expr(
153+
mk().unary_expr(UnOp::Deref(Default::default()), ptr),
154+
val,
155+
);
156+
self.convert_side_effects_expr(
157+
ctx,
158+
WithStmts::new_val(assignment),
159+
"Builtin is not supposed to be used",
160+
)
161+
})
162+
})
163+
}
164+
165+
"__atomic_exchange" | "__atomic_exchange_n" | "__c11_atomic_exchange" => {
135166
let val = val1.expect("__atomic_store must have a val argument");
136167
ptr.and_then(|ptr| {
137168
val.and_then(|val| {
@@ -176,10 +207,22 @@ impl<'c> Translation<'c> {
176207
})
177208
}
178209

179-
"__atomic_compare_exchange" | "__atomic_compare_exchange_n" => {
210+
"__atomic_compare_exchange"
211+
| "__atomic_compare_exchange_n"
212+
| "__c11_atomic_compare_exchange_strong" => {
213+
// TODO(perl): __c11_atomic_compare_exchange_strong does not
214+
// seem to produce correct code. It produces a deref operation
215+
// on the `src` argument to atomic_cxchg_seqcst_seqcst.
180216
let expected =
181217
val1.expect("__atomic_compare_exchange must have a expected argument");
182218
let desired = val2.expect("__atomic_compare_exchange must have a desired argument");
219+
// Some C11 atomic operations encode the weak property in the name
220+
let weak = match (name, weak) {
221+
("__c11_atomic_compare_exchange_strong", None) => Some(false),
222+
("__c11_atomic_compare_exchange_weak", None) => Some(true),
223+
_ => weak,
224+
};
225+
183226
ptr.and_then(|ptr| {
184227
expected.and_then(|expected| {
185228
desired.and_then(|desired| {
@@ -258,7 +301,13 @@ impl<'c> Translation<'c> {
258301
| "__atomic_fetch_and"
259302
| "__atomic_fetch_xor"
260303
| "__atomic_fetch_or"
261-
| "__atomic_fetch_nand" => {
304+
| "__atomic_fetch_nand"
305+
| "__c11_atomic_fetch_add"
306+
| "__c11_atomic_fetch_sub"
307+
| "__c11_atomic_fetch_and"
308+
| "__c11_atomic_fetch_xor"
309+
| "__c11_atomic_fetch_or"
310+
| "__c11_atomic_fetch_nand" => {
262311
let intrinsic_name = if name.contains("_add") {
263312
"atomic_xadd"
264313
} else if name.contains("_sub") {
@@ -276,7 +325,7 @@ impl<'c> Translation<'c> {
276325
let intrinsic_suffix = order_name(static_order(order));
277326
let intrinsic_name = format!("{intrinsic_name}_{intrinsic_suffix}");
278327

279-
let fetch_first = name.starts_with("__atomic_fetch");
328+
let fetch_first = name.starts_with("__atomic_fetch") || name.starts_with("__c11_atomic_fetch");
280329
let val = val1.expect("__atomic arithmetic operations must have a val argument");
281330
ptr.and_then(|ptr| {
282331
val.and_then(|val| {
@@ -285,7 +334,7 @@ impl<'c> Translation<'c> {
285334
})
286335
}
287336

288-
_ => unimplemented!("atomic not implemented"),
337+
_ => unimplemented!("atomic not implemented: {}", name),
289338
}
290339
}
291340

c2rust-transpile/src/translator/mod.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -4426,6 +4426,8 @@ impl<'c> Translation<'c> {
44264426
CastKind::VectorSplat => Err(TranslationError::generic(
44274427
"TODO vector splat casts not supported",
44284428
)),
4429+
4430+
CastKind::AtomicToNonAtomic | CastKind::NonAtomicToAtomic => Ok(val),
44294431
}
44304432
}
44314433

@@ -4934,7 +4936,7 @@ impl<'c> Translation<'c> {
49344936
Vector(..) => {
49354937
// Handled in `import_simd_typedef`
49364938
}
4937-
TypeOfExpr(_) | BuiltinFn => {}
4939+
TypeOfExpr(_) | BuiltinFn | Atomic(..) => {}
49384940
UnhandledSveType => {
49394941
// TODO: handle SVE types
49404942
}

0 commit comments

Comments
 (0)