Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Support C11 atomics required by dav1d #814

Draft
wants to merge 3 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
80 changes: 80 additions & 0 deletions 2c18a0503e1f8ea41b8b94b5771b38a149f8171f.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
From 2c18a0503e1f8ea41b8b94b5771b38a149f8171f Mon Sep 17 00:00:00 2001
From: chrysn <[email protected]>
Date: Wed, 8 Jun 2022 13:26:19 +0200
Subject: [PATCH] C11 atomics: Add tag, move information over to Rust side

---
c2rust-ast-exporter/src/AstExporter.cpp | 22 +++++++++++++---------
c2rust-ast-exporter/src/ast_tags.hpp | 2 ++
c2rust-transpile/src/c_ast/conversion.rs | 5 +++++
3 files changed, 20 insertions(+), 9 deletions(-)

diff --git a/c2rust-ast-exporter/src/AstExporter.cpp b/c2rust-ast-exporter/src/AstExporter.cpp
index 56cce5c93..480a53390 100644
--- a/c2rust-ast-exporter/src/AstExporter.cpp
+++ b/c2rust-ast-exporter/src/AstExporter.cpp
@@ -273,6 +273,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);
@@ -2409,15 +2411,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;
diff --git a/c2rust-ast-exporter/src/ast_tags.hpp b/c2rust-ast-exporter/src/ast_tags.hpp
index 9443d13fc..74e992b05 100644
--- a/c2rust-ast-exporter/src/ast_tags.hpp
+++ b/c2rust-ast-exporter/src/ast_tags.hpp
@@ -142,6 +142,8 @@ enum TypeTag {
TagComplexType,
TagHalf,
TagBFloat16,
+
+ TagAtomicType,
};

enum StringTypeTag {
diff --git a/c2rust-transpile/src/c_ast/conversion.rs b/c2rust-transpile/src/c_ast/conversion.rs
index 45ea7bf81..b31339649 100644
--- a/c2rust-transpile/src/c_ast/conversion.rs
+++ b/c2rust-transpile/src/c_ast/conversion.rs
@@ -826,6 +826,11 @@ impl ConversionContext {
self.processed_nodes.insert(new_id, OTHER_TYPE);
}

+ TypeTag::TagAtomicType => {
+ // Next step in atomics implementation: Transfer to a CTypeKind
+ panic!("C11 Atomics are not implemented in C2Rust yet.");
+ }
+
t => panic!(
"Type conversion not implemented for {:?} expecting {:?}",
t, expected_ty
119 changes: 119 additions & 0 deletions 6c941686f1a230d23685b2fcab104d88391f967a.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
From 6c941686f1a230d23685b2fcab104d88391f967a Mon Sep 17 00:00:00 2001
From: chrysn <[email protected]>
Date: Wed, 8 Jun 2022 13:18:08 +0200
Subject: [PATCH] c2rust-exporter: Remove Atomics warnings

As atomics are being implemented, these warnings are becoming wrong. Any
operations on atomics that stay unimplmented will be caught more
precisely at later translation stages.
---
c2rust-ast-exporter/src/AstExporter.cpp | 54 -------------------------
1 file changed, 54 deletions(-)

diff --git a/c2rust-ast-exporter/src/AstExporter.cpp b/c2rust-ast-exporter/src/AstExporter.cpp
index d5e9e7b68..56cce5c93 100644
--- a/c2rust-ast-exporter/src/AstExporter.cpp
+++ b/c2rust-ast-exporter/src/AstExporter.cpp
@@ -189,24 +189,6 @@ class TypeEncoder final : public TypeVisitor<TypeEncoder> {
astEncoder(ast) {}

void VisitQualType(const QualType &QT) {
- if(isa<AtomicType>(QT)) {
- // No printC11AtomicError available here and no location
- // information either -- should better have been caught at the
- // caller, but catching it here is still better than the
- // nondescript error messages that would come later.
- std::string msg = "C11 Atomics are not supported. No precise "
- "location information available. Aborting.";
-
- auto &DiagEngine = Context->getDiagnostics();
- // Prefix warnings with `c2rust`, so the user can distinguish
- // our warning messages from those generated by clang itself.
- const auto ID = DiagEngine.getCustomDiagID(DiagnosticsEngine::Error,
- "c2rust: %0");
- DiagEngine.Report(SourceLocation::getFromRawEncoding(0), ID).AddString(msg);
-
- abort();
- }
-
if (!QT.isNull()) {
auto s = QT.split();

@@ -1919,10 +1901,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();

@@ -2006,12 +1984,6 @@ class TranslateASTVisitor final
auto recordAlignment = 0;
auto byteSize = 0;

- auto t = D->getTypeForDecl();
- if(isa<AtomicType>(t)) {
- printC11AtomicError(D);
- abort();
- }
-
auto loc = D->getLocation();
std::vector<void *> childIds;
if (def) {
@@ -2084,12 +2056,6 @@ class TranslateASTVisitor final
// They are used in actual code and accepted by compilers, so we cannot
// 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()) {
childIds.push_back(x->getCanonicalDecl());
@@ -2148,10 +2114,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 =
@@ -2206,17 +2168,6 @@ class TranslateASTVisitor final
cbor_encode_boolean(array, D->isImplicit());
});

- if(isa<AtomicType>(typeForDecl)) {
- // This case is especially checked as that's what happens when
- // clang's stdatomic.h is traversed. Other callers of VisitQualType
- // could get the same check to preserve the location information
- // available in Decl but not in Type, but those are more likely not
- // to be hit, and can fall back to the less descriptive error from
- // inside there.
- printC11AtomicError(D);
- abort();
- }
-
typeEncoder.VisitQualType(typeForDecl);

return true;
@@ -2373,11 +2324,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);
47 changes: 15 additions & 32 deletions c2rust-ast-exporter/src/AstExporter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,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 @@ -363,7 +365,7 @@ class TypeEncoder final : public TypeVisitor<TypeEncoder> {
}
}();
// All the SVE types present in Clang 10 are 128-bit vectors
// (see `AArch64SVEACLETypes.def`), so we can divide 128
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unrelated formatting change

// (see `AArch64SVEACLETypes.def`), so we can divide 128
// by their element size to get element count.
auto ElemCount = 128 / Context->getTypeSize(ElemType);
#endif // CLANG_VERSION_MAJOR >= 11
Expand Down Expand Up @@ -403,7 +405,7 @@ class TypeEncoder final : public TypeVisitor<TypeEncoder> {
// Constructed as a consequence of the conversion of
// built-in to normal vector types.
case BuiltinType::Float16: return TagHalf;
case BuiltinType::Half: return TagHalf;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unrelated formatting change.

case BuiltinType::Half: return TagHalf;
#if CLANG_VERSION_MAJOR >= 11
case BuiltinType::BFloat16: return TagBFloat16;
#endif
Expand Down Expand Up @@ -1935,10 +1937,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 @@ -2023,10 +2021,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 @@ -2101,10 +2095,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 @@ -2164,10 +2154,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 @@ -2382,11 +2368,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 @@ -2472,15 +2453,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 @@ -142,6 +142,8 @@ enum TypeTag {
TagComplexType,
TagHalf,
TagBFloat16,

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 @@ -815,6 +817,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 @@ -1756,6 +1766,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,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should really define a fixed operand ordering here in our interchange format, but this technically works.

// 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 @@ -1214,6 +1214,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 @@ -1672,6 +1674,9 @@ pub enum CTypeKind {

Half,
BFloat16,

// 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