llvm-mc: Parse .{,b,p2}align{,w,l} directives.

llvm-svn: 74478
This commit is contained in:
Daniel Dunbar 2009-06-29 23:46:59 +00:00
parent 0a9f9759a3
commit cc566a714b
5 changed files with 124 additions and 8 deletions

View File

@ -135,7 +135,7 @@ namespace llvm {
/// This used to implement the .align assembler directive.
///
/// @param ByteAlignment - The alignment to reach. This must be a power of
/// two.
/// two on some targets.
/// @param Value - The value to use when filling bytes.
/// @param Size - The size of the integer (in bytes) to emit for @param
/// Value. This must match a native machine width.

View File

@ -105,6 +105,7 @@ void MCAsmStreamer::EmitLabel(MCSymbol *Symbol) {
OS << Symbol->getName() << ":\n";
Symbol->setSection(CurSection);
Symbol->setExternal(false);
}
void MCAsmStreamer::EmitAssignment(MCSymbol *Symbol, const MCValue &Value,
@ -164,20 +165,23 @@ void MCAsmStreamer::EmitValue(const MCValue &Value, unsigned Size) {
void MCAsmStreamer::EmitValueToAlignment(unsigned ByteAlignment, int64_t Value,
unsigned ValueSize,
unsigned MaxBytesToEmit) {
// Some assemblers don't support .balign, so we always emit as .p2align if
// this is a power of two. Otherwise we assume the client knows the target
// supports .balign and use that.
unsigned Pow2 = Log2_32(ByteAlignment);
assert((1U << Pow2) == ByteAlignment && "Invalid alignment!");
bool IsPow2 = (1U << Pow2) == ByteAlignment;
switch (ValueSize) {
default:
assert(0 && "Invalid size for machine code value!");
case 8:
assert(0 && "Unsupported alignment size!");
case 1: OS << ".p2align"; break;
case 2: OS << ".p2alignw"; break;
case 4: OS << ".p2alignl"; break;
case 1: OS << (IsPow2 ? ".p2align" : ".balign"); break;
case 2: OS << (IsPow2 ? ".p2alignw" : ".balignw"); break;
case 4: OS << (IsPow2 ? ".p2alignl" : ".balignl"); break;
}
OS << ' ' << Pow2;
OS << ' ' << (IsPow2 ? Pow2 : ByteAlignment);
OS << ", " << truncateToSize(Value, ValueSize);
if (MaxBytesToEmit)

View File

@ -0,0 +1,16 @@
# RUN: llvm-mc %s > %t
# RUN: grep -A 2 TEST0 %t > %t2
# RUN: grep ".p2align 1, 0" %t2 | count 1
TEST0:
.align 1
# RUN: grep -A 2 TEST1 %t > %t2
# RUN: grep ".p2alignl 3, 0, 2" %t2 | count 1
TEST1:
.align32 3,,2
# RUN: grep -A 2 TEST2 %t > %t2
# RUN: grep ".balign 3, 10" %t2 | count 1
TEST2:
.balign 3,10

View File

@ -429,10 +429,30 @@ bool AsmParser::ParseStatement() {
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 @@ bool AsmParser::ParseDirectiveOrg() {
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;
}

View File

@ -79,6 +79,8 @@ private:
bool ParseDirectiveSpace(); // ".space"
bool ParseDirectiveSet(); // ".set"
bool ParseDirectiveOrg(); // ".org"
// ".align{,32}", ".p2align{,w,l}"
bool ParseDirectiveAlign(bool IsPow2, unsigned ValueSize);
};