Index: llvm/trunk/include/llvm/MC/MCTargetAsmParser.h =================================================================== --- llvm/trunk/include/llvm/MC/MCTargetAsmParser.h +++ llvm/trunk/include/llvm/MC/MCTargetAsmParser.h @@ -30,6 +30,7 @@ enum AsmRewriteKind { AOK_Delete = 0, // Rewrite should be ignored. AOK_Align, // Rewrite align as .align. + AOK_EVEN, // Rewrite even as .even. AOK_DotOperator, // Rewrite a dot operator expression as an immediate. // E.g., [eax].foo.bar -> [eax].8 AOK_Emit, // Rewrite _emit as .byte. @@ -45,6 +46,7 @@ const char AsmRewritePrecedence [] = { 0, // AOK_Delete 2, // AOK_Align + 2, // AOK_EVEN 2, // AOK_DotOperator 2, // AOK_Emit 4, // AOK_Imm Index: llvm/trunk/lib/MC/MCParser/AsmParser.cpp =================================================================== --- llvm/trunk/lib/MC/MCParser/AsmParser.cpp +++ llvm/trunk/lib/MC/MCParser/AsmParser.cpp @@ -1714,6 +1714,8 @@ if (ParsingInlineAsm && (IDVal == "align" || IDVal == "ALIGN")) return parseDirectiveMSAlign(IDLoc, Info); + if (ParsingInlineAsm && (IDVal == "even")) + Info.AsmRewrites->emplace_back(AOK_EVEN, IDLoc, 4); checkForValidSection(); // Canonicalize the opcode to lower case. @@ -4863,6 +4865,9 @@ AdditionalSkip = (Val < 4) ? 2 : Val < 7 ? 3 : 4; break; } + case AOK_EVEN: + OS << ".even"; + break; case AOK_DotOperator: // Insert the dot if the user omitted it. OS.flush(); Index: llvm/trunk/lib/Target/X86/AsmParser/X86AsmParser.cpp =================================================================== --- llvm/trunk/lib/Target/X86/AsmParser/X86AsmParser.cpp +++ llvm/trunk/lib/Target/X86/AsmParser/X86AsmParser.cpp @@ -26,6 +26,7 @@ #include "llvm/MC/MCParser/MCAsmParser.h" #include "llvm/MC/MCParser/MCParsedAsmOperand.h" #include "llvm/MC/MCRegisterInfo.h" +#include "llvm/MC/MCSection.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSubtargetInfo.h" #include "llvm/MC/MCSymbol.h" @@ -714,6 +715,7 @@ SMLoc End, unsigned Size, StringRef Identifier, InlineAsmIdentifierInfo &Info); + bool parseDirectiveEven(SMLoc L); bool ParseDirectiveWord(unsigned Size, SMLoc L); bool ParseDirectiveCode(StringRef IDVal, SMLoc L); @@ -2844,10 +2846,29 @@ "a '%' prefix in .intel_syntax"); } return false; - } + } else if (IDVal == ".even") + return parseDirectiveEven(DirectiveID.getLoc()); return true; } +/// parseDirectiveEven +/// ::= .even +bool X86AsmParser::parseDirectiveEven(SMLoc L) { + const MCSection *Section = getStreamer().getCurrentSection().first; + if (getLexer().isNot(AsmToken::EndOfStatement)) { + TokError("unexpected token in directive"); + return false; + } + if (!Section) { + getStreamer().InitSections(false); + Section = getStreamer().getCurrentSection().first; + } + if (Section->UseCodeAlign()) + getStreamer().EmitCodeAlignment(2, 0); + else + getStreamer().EmitValueToAlignment(2, 0, 1, 0); + return false; +} /// ParseDirectiveWord /// ::= .word [ expression (, expression)* ] bool X86AsmParser::ParseDirectiveWord(unsigned Size, SMLoc L) { Index: llvm/trunk/test/MC/X86/x86-evenDirective.s =================================================================== --- llvm/trunk/test/MC/X86/x86-evenDirective.s +++ llvm/trunk/test/MC/X86/x86-evenDirective.s @@ -0,0 +1,47 @@ +# RUN: llvm-mc -filetype obj -o - %s | llvm-readobj -s -sd \ +# RUN: | FileCheck %s + + .text + even_check: + .byte 0x00 + .byte 0x01 + .byte 0x02 + .byte 0x03 + .byte 0x04 + .byte 0x05 + .byte 0x06 + .byte 0x07 + .byte 0x08 + .byte 0x09 + .byte 0x10 + .even + .byte 0x11 + .byte 0x12 + .even + .byte 0x13 + .even + .byte 0x00 + .byte 0x01 + .byte 0x02 + .byte 0x03 + .byte 0x04 + .byte 0x05 + .byte 0x06 + .byte 0x07 + .byte 0x08 + .byte 0x09 + .byte 0x10 + .byte 0x11 + .byte 0x12 + .byte 0x13 + .byte 0x14 + .byte 0x15 + +# CHECK: Section { +# CHECK: Name: .text +# CHECK: SectionData ( +# CHECK: 0000: 00010203 04050607 08091090 11121390 +# CHECK: 0010: 00010203 04050607 08091011 12131415 +# CHECK: ) +# CHECK: } +