summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
diff options
context:
space:
mode:
authorSaleem Abdulrasool <compnerd@compnerd.org>2014-01-21 02:33:10 +0000
committerSaleem Abdulrasool <compnerd@compnerd.org>2014-01-21 02:33:10 +0000
commitd9f086036a50a6b073b6a6c345531d8cc0299330 (patch)
treea4f28cbec15ccfb815a6d645ce764afb2c3e696e /llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
parent662f5c1a5a4c7895efc66a6584dc4ea9653dce9e (diff)
downloadbcm5719-llvm-d9f086036a50a6b073b6a6c345531d8cc0299330.tar.gz
bcm5719-llvm-d9f086036a50a6b073b6a6c345531d8cc0299330.zip
ARM IAS: add support for .unwind_raw directive
This implements the unwind_raw directive for the ARM IAS. The unwind_raw directive takes the form of a stack offset value followed by one or more bytes representing the opcodes to be emitted. The opcode emitted will interpreted as if it were assembled by the opcode assembler via the standard unwinding directives. Thanks to Logan Chien for an extra test! llvm-svn: 199707
Diffstat (limited to 'llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp')
-rw-r--r--llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp84
1 files changed, 84 insertions, 0 deletions
diff --git a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
index 0a1ba9105a7..dc9a308bb95 100644
--- a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
+++ b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
@@ -295,6 +295,7 @@ class ARMAsmParser : public MCTargetAsmParser {
bool parseDirectiveLtorg(SMLoc L);
bool parseDirectiveEven(SMLoc L);
bool parseDirectivePersonalityIndex(SMLoc L);
+ bool parseDirectiveUnwindRaw(SMLoc L);
StringRef splitMnemonic(StringRef Mnemonic, unsigned &PredicationCode,
bool &CarrySetting, unsigned &ProcessorIMod,
@@ -8081,6 +8082,8 @@ bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) {
return parseDirectiveEven(DirectiveID.getLoc());
else if (IDVal == ".personalityindex")
return parseDirectivePersonalityIndex(DirectiveID.getLoc());
+ else if (IDVal == ".unwind_raw")
+ return parseDirectiveUnwindRaw(DirectiveID.getLoc());
return true;
}
@@ -8915,6 +8918,87 @@ bool ARMAsmParser::parseDirectivePersonalityIndex(SMLoc L) {
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;
+}
+
/// Force static initialization.
extern "C" void LLVMInitializeARMAsmParser() {
RegisterMCAsmParser<ARMAsmParser> X(TheARMTarget);
OpenPOWER on IntegriCloud