+ getStreamer().EmitCodeAlignment(2);
+ else
+ getStreamer().EmitValueToAlignment(2);
+
+ return false;
+}
+
+/// parseDirectivePersonalityIndex
+/// ::= .personalityindex index
+bool ARMAsmParser::parseDirectivePersonalityIndex(SMLoc L) {
+ bool HasExistingPersonality = UC.hasPersonality();
+
+ UC.recordPersonalityIndex(L);
+
+ if (!UC.hasFnStart()) {
+ Parser.eatToEndOfStatement();
+ Error(L, ".fnstart must precede .personalityindex directive");
+ return false;
+ }
+ if (UC.cantUnwind()) {
+ Parser.eatToEndOfStatement();
+ Error(L, ".personalityindex cannot be used with .cantunwind");
+ UC.emitCantUnwindLocNotes();
+ return false;
+ }
+ if (UC.hasHandlerData()) {
+ Parser.eatToEndOfStatement();
+ Error(L, ".personalityindex must precede .handlerdata directive");
+ UC.emitHandlerDataLocNotes();
+ return false;
+ }
+ if (HasExistingPersonality) {
+ Parser.eatToEndOfStatement();
+ Error(L, "multiple personality directives");
+ UC.emitPersonalityLocNotes();
+ return false;
+ }
+
+ const MCExpr *IndexExpression;
+ SMLoc IndexLoc = Parser.getTok().getLoc();
+ if (Parser.parseExpression(IndexExpression)) {
+ Parser.eatToEndOfStatement();
+ return false;
+ }
+
+ const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(IndexExpression);
+ if (!CE) {
+ Parser.eatToEndOfStatement();
+ Error(IndexLoc, "index must be a constant number");
+ return false;
+ }
+ if (CE->getValue() < 0 ||
+ CE->getValue() >= ARM::EHABI::NUM_PERSONALITY_INDEX) {
+ Parser.eatToEndOfStatement();
+ Error(IndexLoc, "personality routine index should be in range [0-3]");
+ return false;
+ }
+
+ getTargetStreamer().emitPersonalityIndex(CE->getValue());
+ return false;
+}
+
+/// parseDirectiveUnwindRaw
+/// ::= .unwind_raw offset, opcode [, opcode...]
+bool ARMAsmParser::parseDirectiveUnwindRaw(SMLoc L) {
+ if (!UC.hasFnStart()) {
+ Parser.eatToEndOfStatement();
+ Error(L, ".fnstart must precede .unwind_raw directives");
+ return false;
+ }
+
+ int64_t StackOffset;
+
+ const MCExpr *OffsetExpr;
+ SMLoc OffsetLoc = getLexer().getLoc();
+ if (getLexer().is(AsmToken::EndOfStatement) ||
+ getParser().parseExpression(OffsetExpr)) {
+ Error(OffsetLoc, "expected expression");
+ Parser.eatToEndOfStatement();
+ return false;
+ }
+
+ const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(OffsetExpr);
+ if (!CE) {
+ Error(OffsetLoc, "offset must be a constant");
+ Parser.eatToEndOfStatement();
+ return false;
+ }
+
+ StackOffset = CE->getValue();
+
+ if (getLexer().isNot(AsmToken::Comma)) {
+ Error(getLexer().getLoc(), "expected comma");
+ Parser.eatToEndOfStatement();
+ return false;
+ }
+ Parser.Lex();
+
+ SmallVector<uint8_t, 16> Opcodes;
+ for (;;) {
+ const MCExpr *OE;
+
+ SMLoc OpcodeLoc = getLexer().getLoc();
+ if (getLexer().is(AsmToken::EndOfStatement) || Parser.parseExpression(OE)) {
+ Error(OpcodeLoc, "expected opcode expression");
+ Parser.eatToEndOfStatement();
+ return false;
+ }
+
+ const MCConstantExpr *OC = dyn_cast<MCConstantExpr>(OE);
+ if (!OC) {
+ Error(OpcodeLoc, "opcode value must be a constant");
+ Parser.eatToEndOfStatement();
+ return false;
+ }
+
+ const int64_t Opcode = OC->getValue();
+ if (Opcode & ~0xff) {
+ Error(OpcodeLoc, "invalid opcode");
+ Parser.eatToEndOfStatement();
+ return false;
+ }
+
+ Opcodes.push_back(uint8_t(Opcode));
+
+ if (getLexer().is(AsmToken::EndOfStatement))
+ break;
+
+ if (getLexer().isNot(AsmToken::Comma)) {
+ Error(getLexer().getLoc(), "unexpected token in directive");
+ Parser.eatToEndOfStatement();
+ return false;
+ }
+
+ Parser.Lex();
+ }
+
+ getTargetStreamer().emitUnwindRaw(StackOffset, Opcodes);
+
+ Parser.Lex();
+ return false;
+}
+
+/// parseDirectiveTLSDescSeq
+/// ::= .tlsdescseq tls-variable
+bool ARMAsmParser::parseDirectiveTLSDescSeq(SMLoc L) {
+ if (getLexer().isNot(AsmToken::Identifier)) {
+ TokError("expected variable after '.tlsdescseq' directive");
+ Parser.eatToEndOfStatement();
+ return false;
+ }
+
+ const MCSymbolRefExpr *SRE =
+ MCSymbolRefExpr::Create(Parser.getTok().getIdentifier(),
+ MCSymbolRefExpr::VK_ARM_TLSDESCSEQ, getContext());
+ Lex();
+
+ if (getLexer().isNot(AsmToken::EndOfStatement)) {
+ Error(Parser.getTok().getLoc(), "unexpected token");
+ Parser.eatToEndOfStatement();
+ return false;
+ }
+
+ getTargetStreamer().AnnotateTLSDescriptorSequence(SRE);
+ return false;
+}
+
+/// parseDirectiveMovSP
+/// ::= .movsp reg [, #offset]
+bool ARMAsmParser::parseDirectiveMovSP(SMLoc L) {
+ if (!UC.hasFnStart()) {
+ Parser.eatToEndOfStatement();
+ Error(L, ".fnstart must precede .movsp directives");
+ return false;
+ }
+ if (UC.getFPReg() != ARM::SP) {
+ Parser.eatToEndOfStatement();
+ Error(L, "unexpected .movsp directive");
+ return false;
+ }
+
+ SMLoc SPRegLoc = Parser.getTok().getLoc();
+ int SPReg = tryParseRegister();
+ if (SPReg == -1) {
+ Parser.eatToEndOfStatement();
+ Error(SPRegLoc, "register expected");
+ return false;
+ }
+
+ if (SPReg == ARM::SP || SPReg == ARM::PC) {
+ Parser.eatToEndOfStatement();
+ Error(SPRegLoc, "sp and pc are not permitted in .movsp directive");
+ return false;
+ }
+
+ int64_t Offset = 0;
+ if (Parser.getTok().is(AsmToken::Comma)) {
+ Parser.Lex();
+
+ if (Parser.getTok().isNot(AsmToken::Hash)) {
+ Error(Parser.getTok().getLoc(), "expected #constant");
+ Parser.eatToEndOfStatement();
+ return false;
+ }
+ Parser.Lex();
+
+ const MCExpr *OffsetExpr;
+ SMLoc OffsetLoc = Parser.getTok().getLoc();
+ if (Parser.parseExpression(OffsetExpr)) {
+ Parser.eatToEndOfStatement();
+ Error(OffsetLoc, "malformed offset expression");
+ return false;
+ }
+
+ const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(OffsetExpr);
+ if (!CE) {
+ Parser.eatToEndOfStatement();
+ Error(OffsetLoc, "offset must be an immediate constant");
+ return false;
+ }
+
+ Offset = CE->getValue();
+ }
+
+ getTargetStreamer().emitMovSP(SPReg, Offset);
+ UC.saveFPReg(SPReg);
+
+ return false;
+}
+
+/// parseDirectiveObjectArch
+/// ::= .object_arch name
+bool ARMAsmParser::parseDirectiveObjectArch(SMLoc L) {
+ if (getLexer().isNot(AsmToken::Identifier)) {
+ Error(getLexer().getLoc(), "unexpected token");
+ Parser.eatToEndOfStatement();
+ return false;
+ }
+
+ StringRef Arch = Parser.getTok().getString();
+ SMLoc ArchLoc = Parser.getTok().getLoc();
+ getLexer().Lex();
+
+ unsigned ID = StringSwitch<unsigned>(Arch)
+#define ARM_ARCH_NAME(NAME, ID, DEFAULT_CPU_NAME, DEFAULT_CPU_ARCH) \
+ .Case(NAME, ARM::ID)
+#define ARM_ARCH_ALIAS(NAME, ID) \
+ .Case(NAME, ARM::ID)
+#include "MCTargetDesc/ARMArchName.def"
+#undef ARM_ARCH_NAME
+#undef ARM_ARCH_ALIAS
+ .Default(ARM::INVALID_ARCH);
+
+ if (ID == ARM::INVALID_ARCH) {
+ Error(ArchLoc, "unknown architecture '" + Arch + "'");
+ Parser.eatToEndOfStatement();
+ return false;
+ }
+
+ getTargetStreamer().emitObjectArch(ID);
+
+ if (getLexer().isNot(AsmToken::EndOfStatement)) {
+ Error(getLexer().getLoc(), "unexpected token");
+ Parser.eatToEndOfStatement();
+ }
+
+ return false;
+}
+
+/// parseDirectiveAlign
+/// ::= .align
+bool ARMAsmParser::parseDirectiveAlign(SMLoc L) {
+ // NOTE: if this is not the end of the statement, fall back to the target
+ // agnostic handling for this directive which will correctly handle this.
+ if (getLexer().isNot(AsmToken::EndOfStatement))
+ return true;
+
+ // '.align' is target specifically handled to mean 2**2 byte alignment.
+ if (getStreamer().getCurrentSection().first->UseCodeAlign())
+ getStreamer().EmitCodeAlignment(4, 0);