diff options
Diffstat (limited to 'lib/Target/ARM/AsmParser')
-rw-r--r-- | lib/Target/ARM/AsmParser/ARMAsmParser.cpp | 383 |
1 files changed, 369 insertions, 14 deletions
diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index 114cc9e..c59ca64 100644 --- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -49,6 +49,20 @@ class ARMAsmParser : public MCTargetAsmParser { MCAsmParser &Parser; const MCRegisterInfo *MRI; + // Unwind directives state + SMLoc FnStartLoc; + SMLoc CantUnwindLoc; + SMLoc PersonalityLoc; + SMLoc HandlerDataLoc; + int FPReg; + void resetUnwindDirectiveParserState() { + FnStartLoc = SMLoc(); + CantUnwindLoc = SMLoc(); + PersonalityLoc = SMLoc(); + HandlerDataLoc = SMLoc(); + FPReg = -1; + } + // Map of register aliases registers via the .req directive. StringMap<unsigned> RegisterReqs; @@ -76,7 +90,7 @@ class ARMAsmParser : public MCTargetAsmParser { if (!inITBlock()) return; // Move to the next instruction in the IT block, if there is one. If not, // mark the block as done. - unsigned TZ = CountTrailingZeros_32(ITState.Mask); + unsigned TZ = countTrailingZeros(ITState.Mask); if (++ITState.CurPosition == 5 - TZ) ITState.CurPosition = ~0U; // Done with the IT block after this. } @@ -86,11 +100,11 @@ class ARMAsmParser : public MCTargetAsmParser { MCAsmLexer &getLexer() const { return Parser.getLexer(); } bool Warning(SMLoc L, const Twine &Msg, - ArrayRef<SMRange> Ranges = ArrayRef<SMRange>()) { + ArrayRef<SMRange> Ranges = None) { return Parser.Warning(L, Msg, Ranges); } bool Error(SMLoc L, const Twine &Msg, - ArrayRef<SMRange> Ranges = ArrayRef<SMRange>()) { + ArrayRef<SMRange> Ranges = None) { return Parser.Error(L, Msg, Ranges); } @@ -113,6 +127,14 @@ class ARMAsmParser : public MCTargetAsmParser { bool parseDirectiveUnreq(SMLoc L); bool parseDirectiveArch(SMLoc L); bool parseDirectiveEabiAttr(SMLoc L); + bool parseDirectiveFnStart(SMLoc L); + bool parseDirectiveFnEnd(SMLoc L); + bool parseDirectiveCantUnwind(SMLoc L); + bool parseDirectivePersonality(SMLoc L); + bool parseDirectiveHandlerData(SMLoc L); + bool parseDirectiveSetFP(SMLoc L); + bool parseDirectivePad(SMLoc L); + bool parseDirectiveRegSave(SMLoc L, bool IsVector); StringRef splitMnemonic(StringRef Mnemonic, unsigned &PredicationCode, bool &CarrySetting, unsigned &ProcessorIMod, @@ -130,12 +152,19 @@ class ARMAsmParser : public MCTargetAsmParser { bool isThumbTwo() const { return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2); } + bool hasThumb() const { + return STI.getFeatureBits() & ARM::HasV4TOps; + } bool hasV6Ops() const { return STI.getFeatureBits() & ARM::HasV6Ops; } bool hasV7Ops() const { return STI.getFeatureBits() & ARM::HasV7Ops; } + bool hasARM() const { + return !(STI.getFeatureBits() & ARM::FeatureNoARM); + } + void SwitchMode() { unsigned FB = ComputeAvailableFeatures(STI.ToggleFeature(ARM::ModeThumb)); setAvailableFeatures(FB); @@ -161,6 +190,8 @@ class ARMAsmParser : public MCTargetAsmParser { SmallVectorImpl<MCParsedAsmOperand*>&); OperandMatchResultTy parseMemBarrierOptOperand( SmallVectorImpl<MCParsedAsmOperand*>&); + OperandMatchResultTy parseInstSyncBarrierOptOperand( + SmallVectorImpl<MCParsedAsmOperand*>&); OperandMatchResultTy parseProcIFlagsOperand( SmallVectorImpl<MCParsedAsmOperand*>&); OperandMatchResultTy parseMSRMaskOperand( @@ -242,7 +273,7 @@ public: }; ARMAsmParser(MCSubtargetInfo &_STI, MCAsmParser &_Parser) - : MCTargetAsmParser(), STI(_STI), Parser(_Parser) { + : MCTargetAsmParser(), STI(_STI), Parser(_Parser), FPReg(-1) { MCAsmParserExtension::Initialize(_Parser); // Cache the MCRegisterInfo. @@ -293,6 +324,7 @@ class ARMOperand : public MCParsedAsmOperand { k_CoprocOption, k_Immediate, k_MemBarrierOpt, + k_InstSyncBarrierOpt, k_Memory, k_PostIndexRegister, k_MSRMask, @@ -336,6 +368,10 @@ class ARMOperand : public MCParsedAsmOperand { ARM_MB::MemBOpt Val; }; + struct ISBOptOp { + ARM_ISB::InstSyncBOpt Val; + }; + struct IFlagsOp { ARM_PROC::IFlags Val; }; @@ -422,6 +458,7 @@ class ARMOperand : public MCParsedAsmOperand { struct CopOp Cop; struct CoprocOptionOp CoprocOption; struct MBOptOp MBOpt; + struct ISBOptOp ISBOpt; struct ITMaskOp ITMask; struct IFlagsOp IFlags; struct MMaskOp MMask; @@ -482,6 +519,8 @@ public: case k_MemBarrierOpt: MBOpt = o.MBOpt; break; + case k_InstSyncBarrierOpt: + ISBOpt = o.ISBOpt; case k_Memory: Memory = o.Memory; break; @@ -564,6 +603,11 @@ public: return MBOpt.Val; } + ARM_ISB::InstSyncBOpt getInstSyncBarrierOpt() const { + assert(Kind == k_InstSyncBarrierOpt && "Invalid access!"); + return ISBOpt.Val; + } + ARM_PROC::IFlags getProcIFlags() const { assert(Kind == k_ProcIFlags && "Invalid access!"); return IFlags.Val; @@ -903,6 +947,7 @@ public: bool isSPRRegList() const { return Kind == k_SPRRegisterList; } bool isToken() const { return Kind == k_Token; } bool isMemBarrierOpt() const { return Kind == k_MemBarrierOpt; } + bool isInstSyncBarrierOpt() const { return Kind == k_InstSyncBarrierOpt; } bool isMem() const { return Kind == k_Memory; } bool isShifterImm() const { return Kind == k_ShifterImmediate; } bool isRegShiftedReg() const { return Kind == k_ShiftedRegister; } @@ -949,7 +994,7 @@ public: const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); if (!CE) return false; int64_t Val = CE->getValue(); - return Val > -4096 && Val < 4096; + return (Val == INT32_MIN) || (Val > -4096 && Val < 4096); } bool isAddrMode3() const { // If we have an immediate that's not a constant, treat it as a label @@ -1680,6 +1725,11 @@ public: Inst.addOperand(MCOperand::CreateImm(unsigned(getMemBarrierOpt()))); } + void addInstSyncBarrierOptOperands(MCInst &Inst, unsigned N) const { + assert(N == 1 && "Invalid number of operands!"); + Inst.addOperand(MCOperand::CreateImm(unsigned(getInstSyncBarrierOpt()))); + } + void addMemNoOffsetOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum)); @@ -2345,6 +2395,15 @@ public: return Op; } + static ARMOperand *CreateInstSyncBarrierOpt(ARM_ISB::InstSyncBOpt Opt, + SMLoc S) { + ARMOperand *Op = new ARMOperand(k_InstSyncBarrierOpt); + Op->ISBOpt.Val = Opt; + Op->StartLoc = S; + Op->EndLoc = S; + return Op; + } + static ARMOperand *CreateProcIFlags(ARM_PROC::IFlags IFlags, SMLoc S) { ARMOperand *Op = new ARMOperand(k_ProcIFlags); Op->IFlags.Val = IFlags; @@ -2399,6 +2458,9 @@ void ARMOperand::print(raw_ostream &OS) const { case k_MemBarrierOpt: OS << "<ARM_MB::" << MemBOptToString(getMemBarrierOpt()) << ">"; break; + case k_InstSyncBarrierOpt: + OS << "<ARM_ISB::" << InstSyncBOptToString(getInstSyncBarrierOpt()) << ">"; + break; case k_Memory: OS << "<memory " << " base:" << Memory.BaseRegNum; @@ -3036,7 +3098,7 @@ parseVectorLane(VectorLaneTy &LaneKind, unsigned &Index, SMLoc &EndLoc) { // There's an optional '#' token here. Normally there wouldn't be, but // inline assemble puts one in, and it's friendly to accept that. if (Parser.getTok().is(AsmToken::Hash)) - Parser.Lex(); // Eat the '#' + Parser.Lex(); // Eat '#' or '$'. const MCExpr *LaneIndex; SMLoc Loc = Parser.getTok().getLoc(); @@ -3354,7 +3416,7 @@ parseMemBarrierOptOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { Tok.is(AsmToken::Dollar) || Tok.is(AsmToken::Integer)) { if (Parser.getTok().isNot(AsmToken::Integer)) - Parser.Lex(); // Eat the '#'. + Parser.Lex(); // Eat '#' or '$'. SMLoc Loc = Parser.getTok().getLoc(); const MCExpr *MemBarrierID; @@ -3383,6 +3445,57 @@ parseMemBarrierOptOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { return MatchOperand_Success; } +/// parseInstSyncBarrierOptOperand - Try to parse ISB inst sync barrier options. +ARMAsmParser::OperandMatchResultTy ARMAsmParser:: +parseInstSyncBarrierOptOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { + SMLoc S = Parser.getTok().getLoc(); + const AsmToken &Tok = Parser.getTok(); + unsigned Opt; + + if (Tok.is(AsmToken::Identifier)) { + StringRef OptStr = Tok.getString(); + + if (OptStr.lower() == "sy") + Opt = ARM_ISB::SY; + else + return MatchOperand_NoMatch; + + Parser.Lex(); // Eat identifier token. + } else if (Tok.is(AsmToken::Hash) || + Tok.is(AsmToken::Dollar) || + Tok.is(AsmToken::Integer)) { + if (Parser.getTok().isNot(AsmToken::Integer)) + Parser.Lex(); // Eat '#' or '$'. + SMLoc Loc = Parser.getTok().getLoc(); + + const MCExpr *ISBarrierID; + if (getParser().parseExpression(ISBarrierID)) { + Error(Loc, "illegal expression"); + return MatchOperand_ParseFail; + } + + const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ISBarrierID); + if (!CE) { + Error(Loc, "constant expression expected"); + return MatchOperand_ParseFail; + } + + int Val = CE->getValue(); + if (Val & ~0xf) { + Error(Loc, "immediate value out of range"); + return MatchOperand_ParseFail; + } + + Opt = ARM_ISB::RESERVED_0 + Val; + } else + return MatchOperand_ParseFail; + + Operands.push_back(ARMOperand::CreateInstSyncBarrierOpt( + (ARM_ISB::InstSyncBOpt)Opt, S)); + return MatchOperand_Success; +} + + /// parseProcIFlagsOperand - Try to parse iflags from CPS instruction. ARMAsmParser::OperandMatchResultTy ARMAsmParser:: parseProcIFlagsOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { @@ -3602,7 +3715,7 @@ parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { Error(S, "'be' or 'le' operand expected"); return MatchOperand_ParseFail; } - int Val = StringSwitch<int>(Tok.getString()) + int Val = StringSwitch<int>(Tok.getString().lower()) .Case("be", 1) .Case("le", 0) .Default(-1); @@ -3875,7 +3988,7 @@ parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { // Do immediates first, as we always parse those if we have a '#'. if (Parser.getTok().is(AsmToken::Hash) || Parser.getTok().is(AsmToken::Dollar)) { - Parser.Lex(); // Eat the '#'. + Parser.Lex(); // Eat '#' or '$'. // Explicitly look for a '-', as we need to encode negative zero // differently. bool isNegative = Parser.getTok().is(AsmToken::Minus); @@ -4354,7 +4467,7 @@ parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { Parser.getTok().is(AsmToken::Dollar) || Parser.getTok().is(AsmToken::Integer)) { if (Parser.getTok().isNot(AsmToken::Integer)) - Parser.Lex(); // Eat the '#'. + Parser.Lex(); // Eat '#' or '$'. E = Parser.getTok().getLoc(); bool isNegative = getParser().getTok().is(AsmToken::Minus); @@ -4536,7 +4649,7 @@ parseFPImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { TyOp->getToken() != ".f64")) return MatchOperand_NoMatch; - Parser.Lex(); // Eat the '#'. + Parser.Lex(); // Eat '#' or '$'. // Handle negation, as that still comes through as a separate token. bool isNegative = false; @@ -7398,11 +7511,10 @@ processInstruction(MCInst &Inst, MCOperand &MO = Inst.getOperand(1); unsigned Mask = MO.getImm(); unsigned OrigMask = Mask; - unsigned TZ = CountTrailingZeros_32(Mask); + unsigned TZ = countTrailingZeros(Mask); if ((Inst.getOperand(0).getImm() & 1) == 0) { assert(Mask && TZ <= 3 && "illegal IT mask value!"); - for (unsigned i = 3; i != TZ; --i) - Mask ^= 1 << i; + Mask ^= (0xE << TZ) & 0xF; } MO.setImm(Mask); @@ -7658,6 +7770,24 @@ bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) { return parseDirectiveArch(DirectiveID.getLoc()); else if (IDVal == ".eabi_attribute") return parseDirectiveEabiAttr(DirectiveID.getLoc()); + else if (IDVal == ".fnstart") + return parseDirectiveFnStart(DirectiveID.getLoc()); + else if (IDVal == ".fnend") + return parseDirectiveFnEnd(DirectiveID.getLoc()); + else if (IDVal == ".cantunwind") + return parseDirectiveCantUnwind(DirectiveID.getLoc()); + else if (IDVal == ".personality") + return parseDirectivePersonality(DirectiveID.getLoc()); + else if (IDVal == ".handlerdata") + return parseDirectiveHandlerData(DirectiveID.getLoc()); + else if (IDVal == ".setfp") + return parseDirectiveSetFP(DirectiveID.getLoc()); + else if (IDVal == ".pad") + return parseDirectivePad(DirectiveID.getLoc()); + else if (IDVal == ".save") + return parseDirectiveRegSave(DirectiveID.getLoc(), false); + else if (IDVal == ".vsave") + return parseDirectiveRegSave(DirectiveID.getLoc(), true); return true; } @@ -7693,6 +7823,9 @@ bool ARMAsmParser::parseDirectiveThumb(SMLoc L) { return Error(L, "unexpected token in directive"); Parser.Lex(); + if (!hasThumb()) + return Error(L, "target does not support Thumb mode"); + if (!isThumb()) SwitchMode(); getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16); @@ -7706,6 +7839,9 @@ bool ARMAsmParser::parseDirectiveARM(SMLoc L) { return Error(L, "unexpected token in directive"); Parser.Lex(); + if (!hasARM()) + return Error(L, "target does not support ARM mode"); + if (isThumb()) SwitchMode(); getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32); @@ -7795,10 +7931,16 @@ bool ARMAsmParser::parseDirectiveCode(SMLoc L) { Parser.Lex(); if (Val == 16) { + if (!hasThumb()) + return Error(L, "target does not support Thumb mode"); + if (!isThumb()) SwitchMode(); getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16); } else { + if (!hasARM()) + return Error(L, "target does not support ARM mode"); + if (isThumb()) SwitchMode(); getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32); @@ -7858,6 +8000,219 @@ bool ARMAsmParser::parseDirectiveEabiAttr(SMLoc L) { return true; } +/// parseDirectiveFnStart +/// ::= .fnstart +bool ARMAsmParser::parseDirectiveFnStart(SMLoc L) { + if (FnStartLoc.isValid()) { + Error(L, ".fnstart starts before the end of previous one"); + Error(FnStartLoc, "previous .fnstart starts here"); + return true; + } + + FnStartLoc = L; + getParser().getStreamer().EmitFnStart(); + return false; +} + +/// parseDirectiveFnEnd +/// ::= .fnend +bool ARMAsmParser::parseDirectiveFnEnd(SMLoc L) { + // Check the ordering of unwind directives + if (!FnStartLoc.isValid()) + return Error(L, ".fnstart must precede .fnend directive"); + + // Reset the unwind directives parser state + resetUnwindDirectiveParserState(); + + getParser().getStreamer().EmitFnEnd(); + return false; +} + +/// parseDirectiveCantUnwind +/// ::= .cantunwind +bool ARMAsmParser::parseDirectiveCantUnwind(SMLoc L) { + // Check the ordering of unwind directives + CantUnwindLoc = L; + if (!FnStartLoc.isValid()) + return Error(L, ".fnstart must precede .cantunwind directive"); + if (HandlerDataLoc.isValid()) { + Error(L, ".cantunwind can't be used with .handlerdata directive"); + Error(HandlerDataLoc, ".handlerdata was specified here"); + return true; + } + if (PersonalityLoc.isValid()) { + Error(L, ".cantunwind can't be used with .personality directive"); + Error(PersonalityLoc, ".personality was specified here"); + return true; + } + + getParser().getStreamer().EmitCantUnwind(); + return false; +} + +/// parseDirectivePersonality +/// ::= .personality name +bool ARMAsmParser::parseDirectivePersonality(SMLoc L) { + // Check the ordering of unwind directives + PersonalityLoc = L; + if (!FnStartLoc.isValid()) + return Error(L, ".fnstart must precede .personality directive"); + if (CantUnwindLoc.isValid()) { + Error(L, ".personality can't be used with .cantunwind directive"); + Error(CantUnwindLoc, ".cantunwind was specified here"); + return true; + } + if (HandlerDataLoc.isValid()) { + Error(L, ".personality must precede .handlerdata directive"); + Error(HandlerDataLoc, ".handlerdata was specified here"); + return true; + } + + // Parse the name of the personality routine + if (Parser.getTok().isNot(AsmToken::Identifier)) { + Parser.eatToEndOfStatement(); + return Error(L, "unexpected input in .personality directive."); + } + StringRef Name(Parser.getTok().getIdentifier()); + Parser.Lex(); + + MCSymbol *PR = getParser().getContext().GetOrCreateSymbol(Name); + getParser().getStreamer().EmitPersonality(PR); + return false; +} + +/// parseDirectiveHandlerData +/// ::= .handlerdata +bool ARMAsmParser::parseDirectiveHandlerData(SMLoc L) { + // Check the ordering of unwind directives + HandlerDataLoc = L; + if (!FnStartLoc.isValid()) + return Error(L, ".fnstart must precede .personality directive"); + if (CantUnwindLoc.isValid()) { + Error(L, ".handlerdata can't be used with .cantunwind directive"); + Error(CantUnwindLoc, ".cantunwind was specified here"); + return true; + } + + getParser().getStreamer().EmitHandlerData(); + return false; +} + +/// parseDirectiveSetFP +/// ::= .setfp fpreg, spreg [, offset] +bool ARMAsmParser::parseDirectiveSetFP(SMLoc L) { + // Check the ordering of unwind directives + if (!FnStartLoc.isValid()) + return Error(L, ".fnstart must precede .setfp directive"); + if (HandlerDataLoc.isValid()) + return Error(L, ".setfp must precede .handlerdata directive"); + + // Parse fpreg + SMLoc NewFPRegLoc = Parser.getTok().getLoc(); + int NewFPReg = tryParseRegister(); + if (NewFPReg == -1) + return Error(NewFPRegLoc, "frame pointer register expected"); + + // Consume comma + if (!Parser.getTok().is(AsmToken::Comma)) + return Error(Parser.getTok().getLoc(), "comma expected"); + Parser.Lex(); // skip comma + + // Parse spreg + SMLoc NewSPRegLoc = Parser.getTok().getLoc(); + int NewSPReg = tryParseRegister(); + if (NewSPReg == -1) + return Error(NewSPRegLoc, "stack pointer register expected"); + + if (NewSPReg != ARM::SP && NewSPReg != FPReg) + return Error(NewSPRegLoc, + "register should be either $sp or the latest fp register"); + + // Update the frame pointer register + FPReg = NewFPReg; + + // Parse offset + int64_t Offset = 0; + if (Parser.getTok().is(AsmToken::Comma)) { + Parser.Lex(); // skip comma + + if (Parser.getTok().isNot(AsmToken::Hash) && + Parser.getTok().isNot(AsmToken::Dollar)) { + return Error(Parser.getTok().getLoc(), "'#' expected"); + } + Parser.Lex(); // skip hash token. + + const MCExpr *OffsetExpr; + SMLoc ExLoc = Parser.getTok().getLoc(); + SMLoc EndLoc; + if (getParser().parseExpression(OffsetExpr, EndLoc)) + return Error(ExLoc, "malformed setfp offset"); + const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(OffsetExpr); + if (!CE) + return Error(ExLoc, "setfp offset must be an immediate"); + + Offset = CE->getValue(); + } + + getParser().getStreamer().EmitSetFP(static_cast<unsigned>(NewFPReg), + static_cast<unsigned>(NewSPReg), + Offset); + return false; +} + +/// parseDirective +/// ::= .pad offset +bool ARMAsmParser::parseDirectivePad(SMLoc L) { + // Check the ordering of unwind directives + if (!FnStartLoc.isValid()) + return Error(L, ".fnstart must precede .pad directive"); + if (HandlerDataLoc.isValid()) + return Error(L, ".pad must precede .handlerdata directive"); + + // Parse the offset + if (Parser.getTok().isNot(AsmToken::Hash) && + Parser.getTok().isNot(AsmToken::Dollar)) { + return Error(Parser.getTok().getLoc(), "'#' expected"); + } + Parser.Lex(); // skip hash token. + + const MCExpr *OffsetExpr; + SMLoc ExLoc = Parser.getTok().getLoc(); + SMLoc EndLoc; + if (getParser().parseExpression(OffsetExpr, EndLoc)) + return Error(ExLoc, "malformed pad offset"); + const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(OffsetExpr); + if (!CE) + return Error(ExLoc, "pad offset must be an immediate"); + + getParser().getStreamer().EmitPad(CE->getValue()); + return false; +} + +/// parseDirectiveRegSave +/// ::= .save { registers } +/// ::= .vsave { registers } +bool ARMAsmParser::parseDirectiveRegSave(SMLoc L, bool IsVector) { + // Check the ordering of unwind directives + if (!FnStartLoc.isValid()) + return Error(L, ".fnstart must precede .save or .vsave directives"); + if (HandlerDataLoc.isValid()) + return Error(L, ".save or .vsave must precede .handlerdata directive"); + + // Parse the register list + SmallVector<MCParsedAsmOperand*, 1> Operands; + if (parseRegisterList(Operands)) + return true; + ARMOperand *Op = (ARMOperand*)Operands[0]; + if (!IsVector && !Op->isRegList()) + return Error(L, ".save expects GPR registers"); + if (IsVector && !Op->isDPRRegList()) + return Error(L, ".vsave expects DPR registers"); + + getParser().getStreamer().EmitRegSave(Op->getRegList(), IsVector); + return false; +} + /// Force static initialization. extern "C" void LLVMInitializeARMAsmParser() { RegisterMCAsmParser<ARMAsmParser> X(TheARMTarget); |