diff options
Diffstat (limited to 'llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp')
-rw-r--r-- | llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp | 91 |
1 files changed, 88 insertions, 3 deletions
diff --git a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index 1a3df51acd9..0a1ba9105a7 100644 --- a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -40,6 +40,7 @@ #include "llvm/MC/MCSymbol.h" #include "llvm/MC/MCTargetAsmParser.h" #include "llvm/Support/ARMBuildAttributes.h" +#include "llvm/Support/ARMEHABI.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ELF.h" #include "llvm/Support/MathExtras.h" @@ -121,6 +122,7 @@ class UnwindContext { Locs FnStartLocs; Locs CantUnwindLocs; Locs PersonalityLocs; + Locs PersonalityIndexLocs; Locs HandlerDataLocs; int FPReg; @@ -130,12 +132,15 @@ public: bool hasFnStart() const { return !FnStartLocs.empty(); } bool cantUnwind() const { return !CantUnwindLocs.empty(); } bool hasHandlerData() const { return !HandlerDataLocs.empty(); } - bool hasPersonality() const { return !PersonalityLocs.empty(); } + bool hasPersonality() const { + return !(PersonalityLocs.empty() && PersonalityIndexLocs.empty()); + } void recordFnStart(SMLoc L) { FnStartLocs.push_back(L); } void recordCantUnwind(SMLoc L) { CantUnwindLocs.push_back(L); } void recordPersonality(SMLoc L) { PersonalityLocs.push_back(L); } void recordHandlerData(SMLoc L) { HandlerDataLocs.push_back(L); } + void recordPersonalityIndex(SMLoc L) { PersonalityIndexLocs.push_back(L); } void saveFPReg(int Reg) { FPReg = Reg; } int getFPReg() const { return FPReg; } @@ -157,8 +162,18 @@ public: } void emitPersonalityLocNotes() const { for (Locs::const_iterator PI = PersonalityLocs.begin(), - PE = PersonalityLocs.end(); PI != PE; ++PI) - Parser.Note(*PI, ".personality was specified here"); + PE = PersonalityLocs.end(), + PII = PersonalityIndexLocs.begin(), + PIE = PersonalityIndexLocs.end(); + PI != PE || PII != PIE;) { + if (PI != PE && (PII == PIE || PI->getPointer() < PII->getPointer())) + Parser.Note(*PI++, ".personality was specified here"); + else if (PII != PIE && (PI == PE || PII->getPointer() < PI->getPointer())) + Parser.Note(*PII++, ".personalityindex was specified here"); + else + llvm_unreachable(".personality and .personalityindex cannot be " + "at the same location"); + } } void reset() { @@ -166,6 +181,7 @@ public: CantUnwindLocs = Locs(); PersonalityLocs = Locs(); HandlerDataLocs = Locs(); + PersonalityIndexLocs = Locs(); FPReg = -1; } }; @@ -278,6 +294,7 @@ class ARMAsmParser : public MCTargetAsmParser { bool parseDirectiveInst(SMLoc L, char Suffix = '\0'); bool parseDirectiveLtorg(SMLoc L); bool parseDirectiveEven(SMLoc L); + bool parseDirectivePersonalityIndex(SMLoc L); StringRef splitMnemonic(StringRef Mnemonic, unsigned &PredicationCode, bool &CarrySetting, unsigned &ProcessorIMod, @@ -8062,6 +8079,8 @@ bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) { return parseDirectiveLtorg(DirectiveID.getLoc()); else if (IDVal == ".even") return parseDirectiveEven(DirectiveID.getLoc()); + else if (IDVal == ".personalityindex") + return parseDirectivePersonalityIndex(DirectiveID.getLoc()); return true; } @@ -8454,6 +8473,9 @@ bool ARMAsmParser::parseDirectiveFnStart(SMLoc L) { return false; } + // Reset the unwind directives parser state + UC.reset(); + getTargetStreamer().emitFnStart(); UC.recordFnStart(L); @@ -8504,6 +8526,8 @@ bool ARMAsmParser::parseDirectiveCantUnwind(SMLoc L) { /// parseDirectivePersonality /// ::= .personality name bool ARMAsmParser::parseDirectivePersonality(SMLoc L) { + bool HasExistingPersonality = UC.hasPersonality(); + UC.recordPersonality(L); // Check the ordering of unwind directives @@ -8521,6 +8545,12 @@ bool ARMAsmParser::parseDirectivePersonality(SMLoc L) { UC.emitHandlerDataLocNotes(); return false; } + if (HasExistingPersonality) { + Parser.eatToEndOfStatement(); + Error(L, "multiple personality directives"); + UC.emitPersonalityLocNotes(); + return false; + } // Parse the name of the personality routine if (Parser.getTok().isNot(AsmToken::Identifier)) { @@ -8830,6 +8860,61 @@ bool ARMAsmParser::parseDirectiveEven(SMLoc L) { 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; +} + /// Force static initialization. extern "C" void LLVMInitializeARMAsmParser() { RegisterMCAsmParser<ARMAsmParser> X(TheARMTarget); |