aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp')
-rw-r--r--llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp317
1 files changed, 257 insertions, 60 deletions
diff --git a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
index c7734cc2cf11..b725ea3a84e5 100644
--- a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
+++ b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
@@ -453,6 +453,7 @@ class ARMAsmParser : public MCTargetAsmParser {
bool AllowRAAC = false);
bool parseMemory(OperandVector &);
bool parseOperand(OperandVector &, StringRef Mnemonic);
+ bool parseImmExpr(int64_t &Out);
bool parsePrefix(ARMMCExpr::VariantKind &RefKind);
bool parseMemRegOffsetShift(ARM_AM::ShiftOpc &ShiftType,
unsigned &ShiftAmount);
@@ -488,6 +489,17 @@ class ARMAsmParser : public MCTargetAsmParser {
bool parseDirectiveAlign(SMLoc L);
bool parseDirectiveThumbSet(SMLoc L);
+ bool parseDirectiveSEHAllocStack(SMLoc L, bool Wide);
+ bool parseDirectiveSEHSaveRegs(SMLoc L, bool Wide);
+ bool parseDirectiveSEHSaveSP(SMLoc L);
+ bool parseDirectiveSEHSaveFRegs(SMLoc L);
+ bool parseDirectiveSEHSaveLR(SMLoc L);
+ bool parseDirectiveSEHPrologEnd(SMLoc L, bool Fragment);
+ bool parseDirectiveSEHNop(SMLoc L, bool Wide);
+ bool parseDirectiveSEHEpilogStart(SMLoc L, bool Condition);
+ bool parseDirectiveSEHEpilogEnd(SMLoc L);
+ bool parseDirectiveSEHCustom(SMLoc L);
+
bool isMnemonicVPTPredicable(StringRef Mnemonic, StringRef ExtraToken);
StringRef splitMnemonic(StringRef Mnemonic, StringRef ExtraToken,
unsigned &PredicationCode,
@@ -4528,9 +4540,7 @@ bool ARMAsmParser::parseRegisterList(OperandVector &Operands, bool EnforceOrder,
if (Reg == EndReg)
continue;
// The register must be in the same register class as the first.
- if ((Reg == ARM::RA_AUTH_CODE &&
- RC != &ARMMCRegisterClasses[ARM::GPRRegClassID]) ||
- (Reg != ARM::RA_AUTH_CODE && !RC->contains(Reg)))
+ if (!RC->contains(Reg))
return Error(AfterMinusLoc, "invalid register in register list");
// Ranges must go from low to high.
if (MRI->getEncodingValue(Reg) > MRI->getEncodingValue(EndReg))
@@ -6319,6 +6329,18 @@ bool ARMAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
}
}
+bool ARMAsmParser::parseImmExpr(int64_t &Out) {
+ const MCExpr *Expr = nullptr;
+ SMLoc L = getParser().getTok().getLoc();
+ if (check(getParser().parseExpression(Expr), L, "expected expression"))
+ return true;
+ const MCConstantExpr *Value = dyn_cast_or_null<MCConstantExpr>(Expr);
+ if (check(!Value, L, "expected constant expression"))
+ return true;
+ Out = Value->getValue();
+ return false;
+}
+
// parsePrefix - Parse ARM 16-bit relocations expression prefix, i.e.
// :lower16: and :upper16:.
bool ARMAsmParser::parsePrefix(ARMMCExpr::VariantKind &RefKind) {
@@ -6379,7 +6401,9 @@ bool ARMAsmParser::parsePrefix(ARMMCExpr::VariantKind &RefKind) {
CurrentFormat = WASM;
break;
case MCContext::IsGOFF:
+ case MCContext::IsSPIRV:
case MCContext::IsXCOFF:
+ case MCContext::IsDXContainer:
llvm_unreachable("unexpected object format");
break;
}
@@ -10958,9 +10982,7 @@ bool ARMAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
return true;
}
- { // processInstruction() updates inITBlock state, we need to save it away
- bool wasInITBlock = inITBlock();
-
+ {
// Some instructions need post-processing to, for example, tweak which
// encoding is selected. Loop on it while changes happen so the
// individual transformations can chain off each other. E.g.,
@@ -10969,12 +10991,6 @@ bool ARMAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
LLVM_DEBUG(dbgs() << "Changed to: ";
Inst.dump_pretty(dbgs(), MII.getName(Inst.getOpcode()));
dbgs() << "\n");
-
- // Only after the instruction is fully processed, we can validate it
- if (wasInITBlock && hasV8Ops() && isThumb() &&
- !isV8EligibleForIT(&Inst) && !getTargetOptions().MCNoDeprecatedWarn) {
- Warning(IDLoc, "deprecated instruction in IT block");
- }
}
// Only move forward at the very end so that everything in validate
@@ -11090,6 +11106,39 @@ bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) {
parseDirectiveTLSDescSeq(DirectiveID.getLoc());
else
return true;
+ } else if (IsCOFF) {
+ if (IDVal == ".seh_stackalloc")
+ parseDirectiveSEHAllocStack(DirectiveID.getLoc(), /*Wide=*/false);
+ else if (IDVal == ".seh_stackalloc_w")
+ parseDirectiveSEHAllocStack(DirectiveID.getLoc(), /*Wide=*/true);
+ else if (IDVal == ".seh_save_regs")
+ parseDirectiveSEHSaveRegs(DirectiveID.getLoc(), /*Wide=*/false);
+ else if (IDVal == ".seh_save_regs_w")
+ parseDirectiveSEHSaveRegs(DirectiveID.getLoc(), /*Wide=*/true);
+ else if (IDVal == ".seh_save_sp")
+ parseDirectiveSEHSaveSP(DirectiveID.getLoc());
+ else if (IDVal == ".seh_save_fregs")
+ parseDirectiveSEHSaveFRegs(DirectiveID.getLoc());
+ else if (IDVal == ".seh_save_lr")
+ parseDirectiveSEHSaveLR(DirectiveID.getLoc());
+ else if (IDVal == ".seh_endprologue")
+ parseDirectiveSEHPrologEnd(DirectiveID.getLoc(), /*Fragment=*/false);
+ else if (IDVal == ".seh_endprologue_fragment")
+ parseDirectiveSEHPrologEnd(DirectiveID.getLoc(), /*Fragment=*/true);
+ else if (IDVal == ".seh_nop")
+ parseDirectiveSEHNop(DirectiveID.getLoc(), /*Wide=*/false);
+ else if (IDVal == ".seh_nop_w")
+ parseDirectiveSEHNop(DirectiveID.getLoc(), /*Wide=*/true);
+ else if (IDVal == ".seh_startepilogue")
+ parseDirectiveSEHEpilogStart(DirectiveID.getLoc(), /*Condition=*/false);
+ else if (IDVal == ".seh_startepilogue_cond")
+ parseDirectiveSEHEpilogStart(DirectiveID.getLoc(), /*Condition=*/true);
+ else if (IDVal == ".seh_endepilogue")
+ parseDirectiveSEHEpilogEnd(DirectiveID.getLoc());
+ else if (IDVal == ".seh_custom")
+ parseDirectiveSEHCustom(DirectiveID.getLoc());
+ else
+ return true;
} else
return true;
return false;
@@ -11113,8 +11162,7 @@ bool ARMAsmParser::parseLiteralValues(unsigned Size, SMLoc L) {
/// parseDirectiveThumb
/// ::= .thumb
bool ARMAsmParser::parseDirectiveThumb(SMLoc L) {
- if (parseToken(AsmToken::EndOfStatement, "unexpected token in directive") ||
- check(!hasThumb(), L, "target does not support Thumb mode"))
+ if (parseEOL() || check(!hasThumb(), L, "target does not support Thumb mode"))
return true;
if (!isThumb())
@@ -11127,8 +11175,7 @@ bool ARMAsmParser::parseDirectiveThumb(SMLoc L) {
/// parseDirectiveARM
/// ::= .arm
bool ARMAsmParser::parseDirectiveARM(SMLoc L) {
- if (parseToken(AsmToken::EndOfStatement, "unexpected token in directive") ||
- check(!hasARM(), L, "target does not support ARM mode"))
+ if (parseEOL() || check(!hasARM(), L, "target does not support ARM mode"))
return true;
if (isThumb())
@@ -11167,15 +11214,13 @@ bool ARMAsmParser::parseDirectiveThumbFunc(SMLoc L) {
Parser.getTok().getIdentifier());
getParser().getStreamer().emitThumbFunc(Func);
Parser.Lex();
- if (parseToken(AsmToken::EndOfStatement,
- "unexpected token in '.thumb_func' directive"))
+ if (parseEOL())
return true;
return false;
}
}
- if (parseToken(AsmToken::EndOfStatement,
- "unexpected token in '.thumb_func' directive"))
+ if (parseEOL())
return true;
// .thumb_func implies .thumb
@@ -11204,7 +11249,7 @@ bool ARMAsmParser::parseDirectiveSyntax(SMLoc L) {
"'.syntax divided' arm assembly not supported") ||
check(Mode != "unified" && Mode != "UNIFIED", L,
"unrecognized syntax mode in .syntax directive") ||
- parseToken(AsmToken::EndOfStatement, "unexpected token in directive"))
+ parseEOL())
return true;
// TODO tell the MC streamer the mode
@@ -11226,7 +11271,7 @@ bool ARMAsmParser::parseDirectiveCode(SMLoc L) {
}
Parser.Lex();
- if (parseToken(AsmToken::EndOfStatement, "unexpected token in directive"))
+ if (parseEOL())
return true;
if (Val == 16) {
@@ -11257,8 +11302,7 @@ bool ARMAsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
SMLoc SRegLoc, ERegLoc;
if (check(ParseRegister(Reg, SRegLoc, ERegLoc), SRegLoc,
"register name expected") ||
- parseToken(AsmToken::EndOfStatement,
- "unexpected input in .req directive."))
+ parseEOL())
return true;
if (RegisterReqs.insert(std::make_pair(Name, Reg)).first->second != Reg)
@@ -11276,10 +11320,7 @@ bool ARMAsmParser::parseDirectiveUnreq(SMLoc L) {
return Error(L, "unexpected input in .unreq directive.");
RegisterReqs.erase(Parser.getTok().getIdentifier().lower());
Parser.Lex(); // Eat the identifier.
- if (parseToken(AsmToken::EndOfStatement,
- "unexpected input in '.unreq' directive"))
- return true;
- return false;
+ return parseEOL();
}
// After changing arch/CPU, try to put the ARM/Thumb mode back to what it was
@@ -11340,11 +11381,11 @@ bool ARMAsmParser::parseDirectiveEabiAttr(SMLoc L) {
StringRef Name = Parser.getTok().getIdentifier();
Optional<unsigned> Ret = ELFAttrs::attrTypeFromString(
Name, ARMBuildAttrs::getARMAttributeTags());
- if (!Ret.hasValue()) {
+ if (!Ret) {
Error(TagLoc, "attribute name not recognised: " + Name);
return false;
}
- Tag = Ret.getValue();
+ Tag = *Ret;
Parser.Lex();
} else {
const MCExpr *AttrExpr;
@@ -11406,8 +11447,7 @@ bool ARMAsmParser::parseDirectiveEabiAttr(SMLoc L) {
Parser.Lex();
}
- if (Parser.parseToken(AsmToken::EndOfStatement,
- "unexpected token in '.eabi_attribute' directive"))
+ if (Parser.parseEOL())
return true;
if (IsIntegerValue && IsStringValue) {
@@ -11463,8 +11503,7 @@ bool ARMAsmParser::parseDirectiveFPU(SMLoc L) {
/// parseDirectiveFnStart
/// ::= .fnstart
bool ARMAsmParser::parseDirectiveFnStart(SMLoc L) {
- if (parseToken(AsmToken::EndOfStatement,
- "unexpected token in '.fnstart' directive"))
+ if (parseEOL())
return true;
if (UC.hasFnStart()) {
@@ -11485,8 +11524,7 @@ bool ARMAsmParser::parseDirectiveFnStart(SMLoc L) {
/// parseDirectiveFnEnd
/// ::= .fnend
bool ARMAsmParser::parseDirectiveFnEnd(SMLoc L) {
- if (parseToken(AsmToken::EndOfStatement,
- "unexpected token in '.fnend' directive"))
+ if (parseEOL())
return true;
// Check the ordering of unwind directives
if (!UC.hasFnStart())
@@ -11502,8 +11540,7 @@ bool ARMAsmParser::parseDirectiveFnEnd(SMLoc L) {
/// parseDirectiveCantUnwind
/// ::= .cantunwind
bool ARMAsmParser::parseDirectiveCantUnwind(SMLoc L) {
- if (parseToken(AsmToken::EndOfStatement,
- "unexpected token in '.cantunwind' directive"))
+ if (parseEOL())
return true;
UC.recordCantUnwind(L);
@@ -11538,8 +11575,7 @@ bool ARMAsmParser::parseDirectivePersonality(SMLoc L) {
StringRef Name(Parser.getTok().getIdentifier());
Parser.Lex();
- if (parseToken(AsmToken::EndOfStatement,
- "unexpected token in '.personality' directive"))
+ if (parseEOL())
return true;
UC.recordPersonality(L);
@@ -11571,8 +11607,7 @@ bool ARMAsmParser::parseDirectivePersonality(SMLoc L) {
/// parseDirectiveHandlerData
/// ::= .handlerdata
bool ARMAsmParser::parseDirectiveHandlerData(SMLoc L) {
- if (parseToken(AsmToken::EndOfStatement,
- "unexpected token in '.handlerdata' directive"))
+ if (parseEOL())
return true;
UC.recordHandlerData(L);
@@ -11670,8 +11705,7 @@ bool ARMAsmParser::parseDirectivePad(SMLoc L) {
if (!CE)
return Error(ExLoc, "pad offset must be an immediate");
- if (parseToken(AsmToken::EndOfStatement,
- "unexpected token in '.pad' directive"))
+ if (parseEOL())
return true;
getTargetStreamer().emitPad(CE->getValue());
@@ -11692,8 +11726,7 @@ bool ARMAsmParser::parseDirectiveRegSave(SMLoc L, bool IsVector) {
SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
// Parse the register list
- if (parseRegisterList(Operands, true, true) ||
- parseToken(AsmToken::EndOfStatement, "unexpected token in directive"))
+ if (parseRegisterList(Operands, true, true) || parseEOL())
return true;
ARMOperand &Op = (ARMOperand &)*Operands[0];
if (!IsVector && !Op.isRegList())
@@ -11776,7 +11809,7 @@ bool ARMAsmParser::parseDirectiveInst(SMLoc Loc, char Suffix) {
/// parseDirectiveLtorg
/// ::= .ltorg | .pool
bool ARMAsmParser::parseDirectiveLtorg(SMLoc L) {
- if (parseToken(AsmToken::EndOfStatement, "unexpected token in directive"))
+ if (parseEOL())
return true;
getTargetStreamer().emitCurrentConstantPool();
return false;
@@ -11785,7 +11818,7 @@ bool ARMAsmParser::parseDirectiveLtorg(SMLoc L) {
bool ARMAsmParser::parseDirectiveEven(SMLoc L) {
const MCSection *Section = getStreamer().getCurrentSectionOnly();
- if (parseToken(AsmToken::EndOfStatement, "unexpected token in directive"))
+ if (parseEOL())
return true;
if (!Section) {
@@ -11794,7 +11827,7 @@ bool ARMAsmParser::parseDirectiveEven(SMLoc L) {
}
assert(Section && "must have section to emit alignment");
- if (Section->UseCodeAlign())
+ if (Section->useCodeAlign())
getStreamer().emitCodeAlignment(2, &getSTI());
else
getStreamer().emitValueToAlignment(2);
@@ -11810,9 +11843,7 @@ bool ARMAsmParser::parseDirectivePersonalityIndex(SMLoc L) {
const MCExpr *IndexExpression;
SMLoc IndexLoc = Parser.getTok().getLoc();
- if (Parser.parseExpression(IndexExpression) ||
- parseToken(AsmToken::EndOfStatement,
- "unexpected token in '.personalityindex' directive")) {
+ if (Parser.parseExpression(IndexExpression) || parseEOL()) {
return true;
}
@@ -11913,11 +11944,10 @@ bool ARMAsmParser::parseDirectiveTLSDescSeq(SMLoc L) {
MCSymbolRefExpr::VK_ARM_TLSDESCSEQ, getContext());
Lex();
- if (parseToken(AsmToken::EndOfStatement,
- "unexpected token in '.tlsdescseq' directive"))
+ if (parseEOL())
return true;
- getTargetStreamer().AnnotateTLSDescriptorSequence(SRE);
+ getTargetStreamer().annotateTLSDescriptorSequence(SRE);
return false;
}
@@ -11955,8 +11985,7 @@ bool ARMAsmParser::parseDirectiveMovSP(SMLoc L) {
Offset = CE->getValue();
}
- if (parseToken(AsmToken::EndOfStatement,
- "unexpected token in '.movsp' directive"))
+ if (parseEOL())
return true;
getTargetStreamer().emitMovSP(SPReg, Offset);
@@ -11996,7 +12025,7 @@ bool ARMAsmParser::parseDirectiveAlign(SMLoc L) {
// '.align' is target specifically handled to mean 2**2 byte alignment.
const MCSection *Section = getStreamer().getCurrentSectionOnly();
assert(Section && "must have section to emit alignment");
- if (Section->UseCodeAlign())
+ if (Section->useCodeAlign())
getStreamer().emitCodeAlignment(4, &getSTI(), 0);
else
getStreamer().emitValueToAlignment(4, 0, 1, 0);
@@ -12026,6 +12055,175 @@ bool ARMAsmParser::parseDirectiveThumbSet(SMLoc L) {
return false;
}
+/// parseDirectiveSEHAllocStack
+/// ::= .seh_stackalloc
+/// ::= .seh_stackalloc_w
+bool ARMAsmParser::parseDirectiveSEHAllocStack(SMLoc L, bool Wide) {
+ int64_t Size;
+ if (parseImmExpr(Size))
+ return true;
+ getTargetStreamer().emitARMWinCFIAllocStack(Size, Wide);
+ return false;
+}
+
+/// parseDirectiveSEHSaveRegs
+/// ::= .seh_save_regs
+/// ::= .seh_save_regs_w
+bool ARMAsmParser::parseDirectiveSEHSaveRegs(SMLoc L, bool Wide) {
+ SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
+
+ if (parseRegisterList(Operands) || parseEOL())
+ return true;
+ ARMOperand &Op = (ARMOperand &)*Operands[0];
+ if (!Op.isRegList())
+ return Error(L, ".seh_save_regs{_w} expects GPR registers");
+ const SmallVectorImpl<unsigned> &RegList = Op.getRegList();
+ uint32_t Mask = 0;
+ for (size_t i = 0; i < RegList.size(); ++i) {
+ unsigned Reg = MRI->getEncodingValue(RegList[i]);
+ if (Reg == 15) // pc -> lr
+ Reg = 14;
+ if (Reg == 13)
+ return Error(L, ".seh_save_regs{_w} can't include SP");
+ assert(Reg < 16U && "Register out of range");
+ unsigned Bit = (1u << Reg);
+ Mask |= Bit;
+ }
+ if (!Wide && (Mask & 0x1f00) != 0)
+ return Error(L,
+ ".seh_save_regs cannot save R8-R12, needs .seh_save_regs_w");
+ getTargetStreamer().emitARMWinCFISaveRegMask(Mask, Wide);
+ return false;
+}
+
+/// parseDirectiveSEHSaveSP
+/// ::= .seh_save_sp
+bool ARMAsmParser::parseDirectiveSEHSaveSP(SMLoc L) {
+ int Reg = tryParseRegister();
+ if (Reg == -1 || !MRI->getRegClass(ARM::GPRRegClassID).contains(Reg))
+ return Error(L, "expected GPR");
+ unsigned Index = MRI->getEncodingValue(Reg);
+ if (Index > 14 || Index == 13)
+ return Error(L, "invalid register for .seh_save_sp");
+ getTargetStreamer().emitARMWinCFISaveSP(Index);
+ return false;
+}
+
+/// parseDirectiveSEHSaveFRegs
+/// ::= .seh_save_fregs
+bool ARMAsmParser::parseDirectiveSEHSaveFRegs(SMLoc L) {
+ SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
+
+ if (parseRegisterList(Operands) || parseEOL())
+ return true;
+ ARMOperand &Op = (ARMOperand &)*Operands[0];
+ if (!Op.isDPRRegList())
+ return Error(L, ".seh_save_fregs expects DPR registers");
+ const SmallVectorImpl<unsigned> &RegList = Op.getRegList();
+ uint32_t Mask = 0;
+ for (size_t i = 0; i < RegList.size(); ++i) {
+ unsigned Reg = MRI->getEncodingValue(RegList[i]);
+ assert(Reg < 32U && "Register out of range");
+ unsigned Bit = (1u << Reg);
+ Mask |= Bit;
+ }
+
+ if (Mask == 0)
+ return Error(L, ".seh_save_fregs missing registers");
+
+ unsigned First = 0;
+ while ((Mask & 1) == 0) {
+ First++;
+ Mask >>= 1;
+ }
+ if (((Mask + 1) & Mask) != 0)
+ return Error(L,
+ ".seh_save_fregs must take a contiguous range of registers");
+ unsigned Last = First;
+ while ((Mask & 2) != 0) {
+ Last++;
+ Mask >>= 1;
+ }
+ if (First < 16 && Last >= 16)
+ return Error(L, ".seh_save_fregs must be all d0-d15 or d16-d31");
+ getTargetStreamer().emitARMWinCFISaveFRegs(First, Last);
+ return false;
+}
+
+/// parseDirectiveSEHSaveLR
+/// ::= .seh_save_lr
+bool ARMAsmParser::parseDirectiveSEHSaveLR(SMLoc L) {
+ int64_t Offset;
+ if (parseImmExpr(Offset))
+ return true;
+ getTargetStreamer().emitARMWinCFISaveLR(Offset);
+ return false;
+}
+
+/// parseDirectiveSEHPrologEnd
+/// ::= .seh_endprologue
+/// ::= .seh_endprologue_fragment
+bool ARMAsmParser::parseDirectiveSEHPrologEnd(SMLoc L, bool Fragment) {
+ getTargetStreamer().emitARMWinCFIPrologEnd(Fragment);
+ return false;
+}
+
+/// parseDirectiveSEHNop
+/// ::= .seh_nop
+/// ::= .seh_nop_w
+bool ARMAsmParser::parseDirectiveSEHNop(SMLoc L, bool Wide) {
+ getTargetStreamer().emitARMWinCFINop(Wide);
+ return false;
+}
+
+/// parseDirectiveSEHEpilogStart
+/// ::= .seh_startepilogue
+/// ::= .seh_startepilogue_cond
+bool ARMAsmParser::parseDirectiveSEHEpilogStart(SMLoc L, bool Condition) {
+ unsigned CC = ARMCC::AL;
+ if (Condition) {
+ MCAsmParser &Parser = getParser();
+ SMLoc S = Parser.getTok().getLoc();
+ const AsmToken &Tok = Parser.getTok();
+ if (!Tok.is(AsmToken::Identifier))
+ return Error(S, ".seh_startepilogue_cond missing condition");
+ CC = ARMCondCodeFromString(Tok.getString());
+ if (CC == ~0U)
+ return Error(S, "invalid condition");
+ Parser.Lex(); // Eat the token.
+ }
+
+ getTargetStreamer().emitARMWinCFIEpilogStart(CC);
+ return false;
+}
+
+/// parseDirectiveSEHEpilogEnd
+/// ::= .seh_endepilogue
+bool ARMAsmParser::parseDirectiveSEHEpilogEnd(SMLoc L) {
+ getTargetStreamer().emitARMWinCFIEpilogEnd();
+ return false;
+}
+
+/// parseDirectiveSEHCustom
+/// ::= .seh_custom
+bool ARMAsmParser::parseDirectiveSEHCustom(SMLoc L) {
+ unsigned Opcode = 0;
+ do {
+ int64_t Byte;
+ if (parseImmExpr(Byte))
+ return true;
+ if (Byte > 0xff || Byte < 0)
+ return Error(L, "Invalid byte value in .seh_custom");
+ if (Opcode > 0x00ffffff)
+ return Error(L, "Too many bytes in .seh_custom");
+ // Store the bytes as one big endian number in Opcode. In a multi byte
+ // opcode sequence, the first byte can't be zero.
+ Opcode = (Opcode << 8) | Byte;
+ } while (parseOptionalToken(AsmToken::Comma));
+ getTargetStreamer().emitARMWinCFICustom(Opcode);
+ return false;
+}
+
/// Force static initialization.
extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeARMAsmParser() {
RegisterMCAsmParser<ARMAsmParser> X(getTheARMLETarget());
@@ -12338,8 +12536,7 @@ bool ARMAsmParser::parseDirectiveArchExtension(SMLoc L) {
SMLoc ExtLoc = Parser.getTok().getLoc();
Lex();
- if (parseToken(AsmToken::EndOfStatement,
- "unexpected token in '.arch_extension' directive"))
+ if (parseEOL())
return true;
if (Name == "nocrypto") {