[clang] [flang] [llvm] [clang-tools-extra] [compiler-rt] [clang] Add support for new loop attribute [[clang::code_align()]] (PR #70762)

Erich Keane via cfe-commits cfe-commits at lists.llvm.org
Fri Nov 17 10:00:26 PST 2023


================
@@ -322,6 +322,73 @@ static Attr *handleUnlikely(Sema &S, Stmt *St, const ParsedAttr &A,
   return ::new (S.Context) UnlikelyAttr(S.Context, A);
 }
 
+CodeAlignAttr *Sema::BuildCodeAlignAttr(const AttributeCommonInfo &CI,
+                                        Expr *E) {
+  if (!E->isValueDependent()) {
+    llvm::APSInt ArgVal;
+    ExprResult Res = VerifyIntegerConstantExpression(E, &ArgVal);
+    if (Res.isInvalid())
+      return nullptr;
+    E = Res.get();
+
+    // This attribute requires an integer argument which is a constant power of
+    // two between 1 and 4096 inclusive.
+    if (ArgVal < CodeAlignAttr::MinimumAlignment ||
+        ArgVal > CodeAlignAttr::MaximumAlignment || !ArgVal.isPowerOf2()) {
+      if (std::optional<int64_t> Value = ArgVal.trySExtValue())
+        Diag(CI.getLoc(), diag::err_attribute_power_of_two_in_range)
+            << CI << CodeAlignAttr::MinimumAlignment
+            << CodeAlignAttr::MaximumAlignment << Value.value();
+      else
+        Diag(CI.getLoc(), diag::err_attribute_power_of_two_in_range)
+            << CI << CodeAlignAttr::MinimumAlignment
+            << CodeAlignAttr::MaximumAlignment << E;
+      return nullptr;
+    }
+  }
+  return new (Context) CodeAlignAttr(Context, CI, E);
+}
+
+static Attr *handleCodeAlignAttr(Sema &S, Stmt *St, const ParsedAttr &A) {
+
+  Expr *E = A.getArgAsExpr(0);
+  return S.BuildCodeAlignAttr(A, E);
+}
+
+// Diagnose non-identical duplicates as a 'conflicting' loop attr
+// and suppress duplicate errors in cases where the two match for
+// [[clang::code_align()]] attribute.
+static void
+CheckForDuplicateCodeAlignAttrs(Sema &S,
+                                const SmallVectorImpl<const Attr *> &Attrs) {
+  auto FindFunc = [](const Attr *A) { return isa<const CodeAlignAttr>(A); };
+  const auto *FirstItr = std::find_if(Attrs.begin(), Attrs.end(), FindFunc);
+
+  if (FirstItr == Attrs.end()) // no attributes found
+    return;
+  const auto *LastFoundItr = FirstItr;
+
+  while (Attrs.end() != (LastFoundItr = std::find_if(LastFoundItr + 1,
+                                                     Attrs.end(), FindFunc))) {
+
+    const auto *CEA = dyn_cast<ConstantExpr>(cast<CodeAlignAttr>(*FirstItr)->getAlignment());
+    const auto *CEB = dyn_cast<ConstantExpr>(cast<CodeAlignAttr>(*LastFoundItr)->getAlignment());
+    // If the value is dependent, we can not test anything.
+    if (!CEA || !CEB)
+      return;
+    // Test the attribute value.
+    std::optional<llvm::APSInt> FirstValue = CEA->getResultAsAPSInt();
----------------
erichkeane wrote:

So this would only need to be an optional if it is calculated out of the loop, which, I believe is a good idea to do (and only populate it here if it hasn't been done yet).

Additionally, I think it would be a good idea to return early if we decide that the alignment expression of the first one is dependent (since we don't know what the effective size will be), and skip this loop entirely.

https://github.com/llvm/llvm-project/pull/70762


More information about the cfe-commits mailing list