diff options
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp | 84 | ||||
-rw-r--r-- | llvm/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp | 26 | ||||
-rw-r--r-- | llvm/lib/Target/ARM/MCTargetDesc/ARMUnwindOpAsm.h | 6 |
3 files changed, 116 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); diff --git a/llvm/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp b/llvm/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp index 82543a45f24..79d5619b764 100644 --- a/llvm/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp +++ b/llvm/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp @@ -123,6 +123,8 @@ class ARMTargetAsmStreamer : public ARMTargetStreamer { virtual void emitPad(int64_t Offset); virtual void emitRegSave(const SmallVectorImpl<unsigned> &RegList, bool isVector); + virtual void emitUnwindRaw(int64_t Offset, + const SmallVectorImpl<uint8_t> &Opcodes); virtual void switchVendor(StringRef Vendor); virtual void emitAttribute(unsigned Attribute, unsigned Value); @@ -242,6 +244,16 @@ void ARMTargetAsmStreamer::emitInst(uint32_t Inst, char Suffix) { OS << "\t0x" << utohexstr(Inst) << "\n"; } +void ARMTargetAsmStreamer::emitUnwindRaw(int64_t Offset, + const SmallVectorImpl<uint8_t> &Opcodes) { + OS << "\t.unwind_raw " << Offset; + for (SmallVectorImpl<uint8_t>::const_iterator OCI = Opcodes.begin(), + OCE = Opcodes.end(); + OCI != OCE; ++OCI) + OS << ", 0x" << utohexstr(*OCI); + OS << '\n'; +} + class ARMTargetELFStreamer : public ARMTargetStreamer { private: // This structure holds all attributes, accounting for @@ -367,6 +379,8 @@ private: virtual void emitPad(int64_t Offset); virtual void emitRegSave(const SmallVectorImpl<unsigned> &RegList, bool isVector); + virtual void emitUnwindRaw(int64_t Offset, + const SmallVectorImpl<uint8_t> &Opcodes); virtual void switchVendor(StringRef Vendor); virtual void emitAttribute(unsigned Attribute, unsigned Value); @@ -425,6 +439,7 @@ public: void emitSetFP(unsigned NewFpReg, unsigned NewSpReg, int64_t Offset = 0); void emitPad(int64_t Offset); void emitRegSave(const SmallVectorImpl<unsigned> &RegList, bool isVector); + void emitUnwindRaw(int64_t Offset, const SmallVectorImpl<uint8_t> &Opcodes); virtual void ChangeSection(const MCSection *Section, const MCExpr *Subsection) { @@ -637,6 +652,10 @@ void ARMTargetELFStreamer::emitRegSave(const SmallVectorImpl<unsigned> &RegList, bool isVector) { getStreamer().emitRegSave(RegList, isVector); } +void ARMTargetELFStreamer::emitUnwindRaw(int64_t Offset, + const SmallVectorImpl<uint8_t> &Opcodes) { + getStreamer().emitUnwindRaw(Offset, Opcodes); +} void ARMTargetELFStreamer::switchVendor(StringRef Vendor) { assert(!Vendor.empty() && "Vendor cannot be empty."); @@ -1202,6 +1221,13 @@ void ARMELFStreamer::emitRegSave(const SmallVectorImpl<unsigned> &RegList, UnwindOpAsm.EmitRegSave(Mask); } +void ARMELFStreamer::emitUnwindRaw(int64_t Offset, + const SmallVectorImpl<uint8_t> &Opcodes) { + FlushPendingOffset(); + SPOffset = SPOffset - Offset; + UnwindOpAsm.EmitRaw(Opcodes); +} + namespace llvm { MCStreamer *createMCAsmStreamer(MCContext &Ctx, formatted_raw_ostream &OS, diff --git a/llvm/lib/Target/ARM/MCTargetDesc/ARMUnwindOpAsm.h b/llvm/lib/Target/ARM/MCTargetDesc/ARMUnwindOpAsm.h index b7937535761..e2c44008144 100644 --- a/llvm/lib/Target/ARM/MCTargetDesc/ARMUnwindOpAsm.h +++ b/llvm/lib/Target/ARM/MCTargetDesc/ARMUnwindOpAsm.h @@ -61,6 +61,12 @@ public: /// Emit unwind opcodes to add $sp with an offset. void EmitSPOffset(int64_t Offset); + /// Emit unwind raw opcodes + void EmitRaw(const SmallVectorImpl<uint8_t> &Opcodes) { + Ops.insert(Ops.end(), Opcodes.begin(), Opcodes.end()); + OpBegins.push_back(OpBegins.back() + Opcodes.size()); + } + /// Finalize the unwind opcode sequence for EmitBytes() void Finalize(unsigned &PersonalityIndex, SmallVectorImpl<uint8_t> &Result); |