Skip to content

Commit

Permalink
merge immunant#814
Browse files Browse the repository at this point in the history
  • Loading branch information
Nugine committed Dec 8, 2024
2 parents 85554d2 + 042845b commit 0b9db95
Show file tree
Hide file tree
Showing 8 changed files with 97 additions and 39 deletions.
43 changes: 13 additions & 30 deletions c2rust-ast-exporter/src/AstExporter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,8 @@ class TypeEncoder final : public TypeVisitor<TypeEncoder> {

void VisitVariableArrayType(const VariableArrayType *T);

void VisitAtomicType(const AtomicType *AT);

void VisitIncompleteArrayType(const IncompleteArrayType *T) {
auto t = T->getElementType();
auto qt = encodeQualType(t);
Expand Down Expand Up @@ -1960,10 +1962,6 @@ class TranslateASTVisitor final
// Use the type from the definition in case the extern was an incomplete
// type
auto T = def->getType();
if (isa<AtomicType>(T)) {
printC11AtomicError(def);
abort();
}

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

Expand Down Expand Up @@ -2048,10 +2046,6 @@ class TranslateASTVisitor final
auto byteSize = 0;

auto t = D->getTypeForDecl();
if (isa<AtomicType>(t)) {
printC11AtomicError(D);
abort();
}

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

auto t = D->getTypeForDecl();
if (isa<AtomicType>(t)) {
printC11AtomicError(D);
abort();
}

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

std::vector<void *> childIds;
auto t = D->getType();
if (isa<AtomicType>(t)) {
printC11AtomicError(D);
abort();
}

auto record = D->getParent();
const ASTRecordLayout &layout =
Expand Down Expand Up @@ -2434,11 +2420,6 @@ class TranslateASTVisitor final
CharSourceRange::getCharRange(E->getSourceRange()));
}

void printC11AtomicError(Decl *D) {
std::string msg = "C11 Atomics are not supported. Aborting.";
printError(msg, D);
}

void printError(std::string Message, Decl *D) {
auto DiagBuilder =
getDiagBuilder(D->getLocation(), DiagnosticsEngine::Error);
Expand Down Expand Up @@ -2524,15 +2505,17 @@ void TypeEncoder::VisitVariableArrayType(const VariableArrayType *T) {

VisitQualType(t);
}
//
//void TypeEncoder::VisitAtomicType(const AtomicType *AT) {
// std::string msg =
// "C11 Atomic types are not supported. Aborting.";
//// auto horse = AT->get
//// astEncoder->printError(msg, AT);
// AT->getValueType()->dump();
// abort();
//}

void TypeEncoder::VisitAtomicType(const AtomicType *AT) {
auto t = AT->getValueType();
auto qt = encodeQualType(t);

encodeType(AT, TagAtomicType, [qt](CborEncoder *local) {
cbor_encode_uint(local, qt);
});

VisitQualType(t);
}

class TranslateConsumer : public clang::ASTConsumer {
Outputs *outputs;
Expand Down
2 changes: 2 additions & 0 deletions c2rust-ast-exporter/src/ast_tags.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,8 @@ enum TypeTag {
TagSveBool,
TagSveBoolx2,
TagSveBoolx4,

TagAtomicType,
};

enum StringTypeTag {
Expand Down
15 changes: 15 additions & 0 deletions c2rust-transpile/src/c_ast/conversion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,8 @@ fn parse_cast_kind(kind: &str) -> CastKind {
"BuiltinFnToFnPtr" => CastKind::BuiltinFnToFnPtr,
"ConstCast" => CastKind::ConstCast,
"VectorSplat" => CastKind::VectorSplat,
"AtomicToNonAtomic" => CastKind::AtomicToNonAtomic,
"NonAtomicToAtomic" => CastKind::NonAtomicToAtomic,
k => panic!("Unsupported implicit cast: {}", k),
}
}
Expand Down Expand Up @@ -824,6 +826,14 @@ impl ConversionContext {
self.processed_nodes.insert(new_id, OTHER_TYPE);
}

TypeTag::TagAtomicType => {
let qt = from_value(ty_node.extras[0].clone()).expect("Inner type not found");
let qt_new = self.visit_qualified_type(qt);
let atomic_ty = CTypeKind::Atomic(qt_new);
self.add_type(new_id, not_located(atomic_ty));
self.processed_nodes.insert(new_id, OTHER_TYPE);
}

t => panic!(
"Type conversion not implemented for {:?} expecting {:?}",
t, expected_ty
Expand Down Expand Up @@ -1765,6 +1775,11 @@ impl ConversionContext {
let typ = node.type_id.expect("Expected expression to have type");
let typ = self.visit_qualified_type(typ);

// Perhaps as an optimization since atomic_init has no order,
// clang stores val1 in the position otherwise used for order
let is_atomic = name == "__c11_atomic_init" || name == "__opencl_atomic_init";
let val1 = if is_atomic { Some(order) } else { val1 };

let e = CExprKind::Atomic {
typ,
name,
Expand Down
3 changes: 2 additions & 1 deletion c2rust-transpile/src/c_ast/iterators.rs
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,8 @@ fn immediate_type_children(kind: &CTypeKind) -> Vec<SomeId> {
| Reference(qtype)
| Attributed(qtype, _)
| BlockPointer(qtype)
| Vector(qtype, _) => {
| Vector(qtype, _)
| Atomic(qtype) => {
intos![qtype.ctype]
}

Expand Down
5 changes: 5 additions & 0 deletions c2rust-transpile/src/c_ast/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1223,6 +1223,8 @@ pub enum CastKind {
BuiltinFnToFnPtr,
ConstCast,
VectorSplat,
AtomicToNonAtomic,
NonAtomicToAtomic,
}

/// Represents a unary operator in C (6.5.3 Unary operators) and GNU C extensions
Expand Down Expand Up @@ -1685,6 +1687,9 @@ pub enum CTypeKind {
// ARM Scalable Vector Extention types
// TODO: represent all the individual types in AArch64SVEACLETypes.def
UnhandledSveType,

// Atomic types (6.7.2.4)
Atomic(CQualTypeId),
}

impl CTypeKind {
Expand Down
1 change: 1 addition & 0 deletions c2rust-transpile/src/convert_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -380,6 +380,7 @@ impl TypeConverter {
}

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

// ANSI/ISO C-style function
CTypeKind::Function(ret, ref params, is_var, is_noreturn, true) => {
Expand Down
63 changes: 56 additions & 7 deletions c2rust-transpile/src/translator/atomics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,19 @@ impl<'c> Translation<'c> {
let memorder = &self.ast_context[expr];
let i = match memorder.kind {
CExprKind::Literal(_, CLiteral::Integer(i, _)) => Some(i),
CExprKind::DeclRef(_, decl_id, LRValue::RValue) => {
let decl = self.ast_context.get_decl(&decl_id).unwrap();
match decl.kind {
CDeclKind::EnumConstant { name: _, value: v } => match v {
ConstIntExpr::I(i) => {
assert!(0 <= i);
Some(i as u64)
}
ConstIntExpr::U(u) => Some(u),
},
_ => unimplemented!(),
}
}
_ => None,
}?;
use Ordering::*;
Expand Down Expand Up @@ -76,7 +89,7 @@ impl<'c> Translation<'c> {
}

match name {
"__atomic_load" | "__atomic_load_n" => ptr.and_then(|ptr| {
"__atomic_load" | "__atomic_load_n" | "__c11_atomic_load" => ptr.and_then(|ptr| {
let intrinsic_name = format!("atomic_load_{}", order_name(static_order(order)));

self.use_feature("core_intrinsics");
Expand Down Expand Up @@ -105,7 +118,7 @@ impl<'c> Translation<'c> {
}
}),

"__atomic_store" | "__atomic_store_n" => {
"__atomic_store" | "__atomic_store_n" | "__c11_atomic_store" => {
let val = val1.expect("__atomic_store must have a val argument");
ptr.and_then(|ptr| {
val.and_then(|val| {
Expand All @@ -131,7 +144,25 @@ impl<'c> Translation<'c> {
})
}

"__atomic_exchange" | "__atomic_exchange_n" => {
// NOTE: there is no corresponding __atomic_init builtin in clang
"__c11_atomic_init" => {
let val = val1.expect(&format!("__atomic_init must have a val argument"));
ptr.and_then(|ptr| {
val.and_then(|val| {
let assignment = mk().assign_expr(
mk().unary_expr(UnOp::Deref(Default::default()), ptr),
val,
);
self.convert_side_effects_expr(
ctx,
WithStmts::new_val(assignment),
"Builtin is not supposed to be used",
)
})
})
}

"__atomic_exchange" | "__atomic_exchange_n" | "__c11_atomic_exchange" => {
let val = val1.expect("__atomic_store must have a val argument");
ptr.and_then(|ptr| {
val.and_then(|val| {
Expand Down Expand Up @@ -176,10 +207,22 @@ impl<'c> Translation<'c> {
})
}

"__atomic_compare_exchange" | "__atomic_compare_exchange_n" => {
"__atomic_compare_exchange"
| "__atomic_compare_exchange_n"
| "__c11_atomic_compare_exchange_strong" => {
// TODO(perl): __c11_atomic_compare_exchange_strong does not
// seem to produce correct code. It produces a deref operation
// on the `src` argument to atomic_cxchg_seqcst_seqcst.
let expected =
val1.expect("__atomic_compare_exchange must have a expected argument");
let desired = val2.expect("__atomic_compare_exchange must have a desired argument");
// Some C11 atomic operations encode the weak property in the name
let weak = match (name, weak) {
("__c11_atomic_compare_exchange_strong", None) => Some(false),
("__c11_atomic_compare_exchange_weak", None) => Some(true),
_ => weak,
};

ptr.and_then(|ptr| {
expected.and_then(|expected| {
desired.and_then(|desired| {
Expand Down Expand Up @@ -258,7 +301,13 @@ impl<'c> Translation<'c> {
| "__atomic_fetch_and"
| "__atomic_fetch_xor"
| "__atomic_fetch_or"
| "__atomic_fetch_nand" => {
| "__atomic_fetch_nand"
| "__c11_atomic_fetch_add"
| "__c11_atomic_fetch_sub"
| "__c11_atomic_fetch_and"
| "__c11_atomic_fetch_xor"
| "__c11_atomic_fetch_or"
| "__c11_atomic_fetch_nand" => {
let intrinsic_name = if name.contains("_add") {
"atomic_xadd"
} else if name.contains("_sub") {
Expand All @@ -276,7 +325,7 @@ impl<'c> Translation<'c> {
let intrinsic_suffix = order_name(static_order(order));
let intrinsic_name = format!("{intrinsic_name}_{intrinsic_suffix}");

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

_ => unimplemented!("atomic not implemented"),
_ => unimplemented!("atomic not implemented: {}", name),
}
}

Expand Down
4 changes: 3 additions & 1 deletion c2rust-transpile/src/translator/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4426,6 +4426,8 @@ impl<'c> Translation<'c> {
CastKind::VectorSplat => Err(TranslationError::generic(
"TODO vector splat casts not supported",
)),

CastKind::AtomicToNonAtomic | CastKind::NonAtomicToAtomic => Ok(val),
}
}

Expand Down Expand Up @@ -4934,7 +4936,7 @@ impl<'c> Translation<'c> {
Vector(..) => {
// Handled in `import_simd_typedef`
}
TypeOfExpr(_) | BuiltinFn => {}
TypeOfExpr(_) | BuiltinFn | Atomic(..) => {}
UnhandledSveType => {
// TODO: handle SVE types
}
Expand Down

0 comments on commit 0b9db95

Please sign in to comment.