llvm-mc: Parse .{,b,p2}align{,w,l} directives.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@74478 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/tools/llvm-mc/AsmParser.cpp b/tools/llvm-mc/AsmParser.cpp
index 4cb515b..29222d4 100644
--- a/tools/llvm-mc/AsmParser.cpp
+++ b/tools/llvm-mc/AsmParser.cpp
@@ -429,10 +429,30 @@
return ParseDirectiveValue(4);
if (!strcmp(IDVal, ".quad"))
return ParseDirectiveValue(8);
- if (!strcmp(IDVal, ".fill"))
- return ParseDirectiveFill();
+
+ // FIXME: Target hooks for IsPow2.
+ if (!strcmp(IDVal, ".align"))
+ return ParseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/1);
+ if (!strcmp(IDVal, ".align32"))
+ return ParseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/4);
+ if (!strcmp(IDVal, ".balign"))
+ return ParseDirectiveAlign(/*IsPow2=*/false, /*ExprSize=*/1);
+ if (!strcmp(IDVal, ".balignw"))
+ return ParseDirectiveAlign(/*IsPow2=*/false, /*ExprSize=*/2);
+ if (!strcmp(IDVal, ".balignl"))
+ return ParseDirectiveAlign(/*IsPow2=*/false, /*ExprSize=*/4);
+ if (!strcmp(IDVal, ".p2align"))
+ return ParseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/1);
+ if (!strcmp(IDVal, ".p2alignw"))
+ return ParseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/2);
+ if (!strcmp(IDVal, ".p2alignl"))
+ return ParseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/4);
+
if (!strcmp(IDVal, ".org"))
return ParseDirectiveOrg();
+
+ if (!strcmp(IDVal, ".fill"))
+ return ParseDirectiveFill();
if (!strcmp(IDVal, ".space"))
return ParseDirectiveSpace();
@@ -708,3 +728,77 @@
return false;
}
+
+/// ParseDirectiveAlign
+/// ::= {.align, ...} expression [ , expression [ , expression ]]
+bool AsmParser::ParseDirectiveAlign(bool IsPow2, unsigned ValueSize) {
+ int64_t Alignment;
+ if (ParseAbsoluteExpression(Alignment))
+ return true;
+
+ SMLoc MaxBytesLoc;
+ bool HasFillExpr = false;
+ int64_t FillExpr = 0;
+ int64_t MaxBytesToFill = 0;
+ if (Lexer.isNot(asmtok::EndOfStatement)) {
+ if (Lexer.isNot(asmtok::Comma))
+ return TokError("unexpected token in directive");
+ Lexer.Lex();
+
+ // The fill expression can be omitted while specifying a maximum number of
+ // alignment bytes, e.g:
+ // .align 3,,4
+ if (Lexer.isNot(asmtok::Comma)) {
+ HasFillExpr = true;
+ if (ParseAbsoluteExpression(FillExpr))
+ return true;
+ }
+
+ if (Lexer.isNot(asmtok::EndOfStatement)) {
+ if (Lexer.isNot(asmtok::Comma))
+ return TokError("unexpected token in directive");
+ Lexer.Lex();
+
+ MaxBytesLoc = Lexer.getLoc();
+ if (ParseAbsoluteExpression(MaxBytesToFill))
+ return true;
+
+ if (Lexer.isNot(asmtok::EndOfStatement))
+ return TokError("unexpected token in directive");
+ }
+ }
+
+ Lexer.Lex();
+
+ if (!HasFillExpr) {
+ // FIXME: Sometimes fill with nop.
+ FillExpr = 0;
+ }
+
+ // Compute alignment in bytes.
+ if (IsPow2) {
+ // FIXME: Diagnose overflow.
+ Alignment = 1 << Alignment;
+ }
+
+ // Diagnose non-sensical max bytes to fill.
+ if (MaxBytesLoc.isValid()) {
+ if (MaxBytesToFill < 1) {
+ Lexer.PrintMessage(MaxBytesLoc, "warning: alignment directive can never "
+ "be satisfied in this many bytes, ignoring");
+ return false;
+ }
+
+ if (MaxBytesToFill >= Alignment) {
+ Lexer.PrintMessage(MaxBytesLoc, "warning: maximum bytes expression "
+ "exceeds alignment and has no effect");
+ MaxBytesToFill = 0;
+ }
+ }
+
+ // FIXME: Target specific behavior about how the "extra" bytes are filled.
+ Out.EmitValueToAlignment(Alignment, FillExpr, ValueSize, MaxBytesToFill);
+
+ return false;
+}
+