[llvm] [SystemZ][z/OS] Emit alignment in HLASM syntax (PR #222121)

Ulrich Weigand via llvm-commits llvm-commits at lists.llvm.org
Wed Sep 9 06:59:34 PDT 2026


================
@@ -310,30 +281,77 @@ void SystemZHLASMAsmStreamer::EmitComment() {
   CommentToEmit.clear();
 }
 
+void SystemZHLASMAsmStreamer::flushPendingAlignment() {
+  if (!PendingAlignSuffix)
+    return;
+  OS << " DS 0" << *PendingAlignSuffix;
+  EmitEOL();
+  PendingAlignSuffix.reset();
+}
+
 void SystemZHLASMAsmStreamer::emitValueToAlignment(Align Alignment,
                                                    int64_t Fill,
                                                    uint8_t FillLen,
                                                    unsigned MaxBytesToEmit) {
-  emitAlignmentDS(Alignment.value(), Fill, FillLen, MaxBytesToEmit);
+  unsigned int A = Log2(Alignment);
+  if (A > 12)
+    return getContext().reportError(SMLoc(), "Alignment > 4096 not supported");
+  if (FillLen > 1)
+    return getContext().reportError(SMLoc(), "Fill length > 1 not supported");
+  if (Fill == 0 && A < 5) {
+    // Simple form: defer so the next emitLabel() can absorb it (e.g. "foo DS
+    // 0H" instead of a standalone "DS 0H" followed by "foo DS 0B").
+    flushPendingAlignment();
+    static const char SUFFIX[5] = {'B', 'H', 'F', 'D', 'Q'};
+    PendingAlignSuffix = SUFFIX[A];
+  } else if (A) {
+    // Non-simple form with a fill value. The HLASM DC duplication factor must
+    // be an absolute expression, so we cannot use the location counter (*)
+    // directly — it is a relocatable term. We also cannot use & as a bitwise
+    // AND operator, as ordinary HLASM expressions only support +, -, *, /.
+    //
+    // The solution is to introduce a temporary EQU symbol P defined as
+    // (*-SECTION), which is the difference of two co-relocatable terms and
+    // therefore absolute. With that absolute offset P and boundary B the
+    // padding count is:
+    //
+    //   B - (P - ((P-1)/B)*B)
+    //
+    // which is the integer-division modulo idiom. The (P-1) bias ensures the
+    // count is 0 (not B) when already aligned.
+    unsigned int B = 1 << A;
+    // Retrieve the section name as the relocatable anchor (&POINT equivalent).
+    StringRef Anchor =
+        getCurrentSectionOnly()->getBeginSymbol()
+            ? getCurrentSectionOnly()->getBeginSymbol()->getName()
+            : static_cast<MCSectionGOFF *>(getCurrentSectionOnly())->getName();
+    // Emit the temporary EQU (P = *-Anchor) on its own line.
+    MCSymbol *Pad = getContext().createNamedTempSymbol("PAD");
+    MCStreamer::emitLabel(Pad);
+    StringRef PSym = Pad->getName();
+    OS << PSym << " EQU *-" << Anchor;
+    EmitEOL();
+    // Emit the DC with the fill value and computed duplication factor.
+    OS << " DC (" << B << "-(" << PSym << "-((" << PSym << "-1)/" << B << ")*"
+       << B << "))";
+    // Append the fill constant operand: XL1'xx'.
+    OS << "XL1'" << utohexstr(Fill, /*LowerCase=*/false, 2) << "'";
+    EmitEOL();
+  }
 }
 
 void SystemZHLASMAsmStreamer::emitCodeAlignment(Align Alignment,
                                                 const MCSubtargetInfo &STI,
                                                 unsigned MaxBytesToEmit) {
-  // Emit with a text fill value.
-  if (MAI->getTextAlignFillValue())
-    emitAlignmentDS(Alignment.value(), MAI->getTextAlignFillValue(), 1,
-                    MaxBytesToEmit);
-  else
-    emitAlignmentDS(Alignment.value(), std::nullopt, 1, MaxBytesToEmit);
+  emitValueToAlignment(Alignment, 0, 1, MaxBytesToEmit);
----------------
uweigand wrote:

This now simply ignores `getTextAlignFillValue` ?

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


More information about the llvm-commits mailing list