diff options
Diffstat (limited to 'lib/Target/X86/AsmParser')
-rw-r--r-- | lib/Target/X86/AsmParser/X86AsmInstrumentation.cpp | 102 | ||||
-rw-r--r-- | lib/Target/X86/AsmParser/X86AsmParser.cpp | 221 | ||||
-rw-r--r-- | lib/Target/X86/AsmParser/X86AsmParserCommon.h | 5 | ||||
-rw-r--r-- | lib/Target/X86/AsmParser/X86Operand.h | 75 |
4 files changed, 268 insertions, 135 deletions
diff --git a/lib/Target/X86/AsmParser/X86AsmInstrumentation.cpp b/lib/Target/X86/AsmParser/X86AsmInstrumentation.cpp index 9c49a11..543af8e 100644 --- a/lib/Target/X86/AsmParser/X86AsmInstrumentation.cpp +++ b/lib/Target/X86/AsmParser/X86AsmInstrumentation.cpp @@ -165,9 +165,9 @@ public: } unsigned ChooseFrameReg(MVT::SimpleValueType VT) const { - static const unsigned Candidates[] = { X86::RBP, X86::RAX, X86::RBX, - X86::RCX, X86::RDX, X86::RDI, - X86::RSI }; + static const MCPhysReg Candidates[] = { X86::RBP, X86::RAX, X86::RBX, + X86::RCX, X86::RDX, X86::RDI, + X86::RSI }; for (unsigned Reg : Candidates) { if (!std::count(BusyRegs.begin(), BusyRegs.end(), Reg)) return convReg(Reg, VT); @@ -261,6 +261,23 @@ protected: int64_t Displacement, MCContext &Ctx, int64_t *Residue); + bool is64BitMode() const { + return (STI.getFeatureBits() & X86::Mode64Bit) != 0; + } + bool is32BitMode() const { + return (STI.getFeatureBits() & X86::Mode32Bit) != 0; + } + bool is16BitMode() const { + return (STI.getFeatureBits() & X86::Mode16Bit) != 0; + } + + unsigned getPointerWidth() { + if (is16BitMode()) return 16; + if (is32BitMode()) return 32; + if (is64BitMode()) return 64; + llvm_unreachable("invalid mode"); + } + // True when previous instruction was actually REP prefix. bool RepPrefix; @@ -301,7 +318,7 @@ void X86AddressSanitizer::InstrumentMOVSBase(unsigned DstReg, unsigned SrcReg, { const MCExpr *Disp = MCConstantExpr::Create(0, Ctx); std::unique_ptr<X86Operand> Op(X86Operand::CreateMem( - 0, Disp, SrcReg, 0, AccessSize, SMLoc(), SMLoc())); + getPointerWidth(), 0, Disp, SrcReg, 0, AccessSize, SMLoc(), SMLoc())); InstrumentMemOperand(*Op, AccessSize, false /* IsWrite */, RegCtx, Ctx, Out); } @@ -310,7 +327,8 @@ void X86AddressSanitizer::InstrumentMOVSBase(unsigned DstReg, unsigned SrcReg, { const MCExpr *Disp = MCConstantExpr::Create(-1, Ctx); std::unique_ptr<X86Operand> Op(X86Operand::CreateMem( - 0, Disp, SrcReg, CntReg, AccessSize, SMLoc(), SMLoc())); + getPointerWidth(), 0, Disp, SrcReg, CntReg, AccessSize, SMLoc(), + SMLoc())); InstrumentMemOperand(*Op, AccessSize, false /* IsWrite */, RegCtx, Ctx, Out); } @@ -319,7 +337,7 @@ void X86AddressSanitizer::InstrumentMOVSBase(unsigned DstReg, unsigned SrcReg, { const MCExpr *Disp = MCConstantExpr::Create(0, Ctx); std::unique_ptr<X86Operand> Op(X86Operand::CreateMem( - 0, Disp, DstReg, 0, AccessSize, SMLoc(), SMLoc())); + getPointerWidth(), 0, Disp, DstReg, 0, AccessSize, SMLoc(), SMLoc())); InstrumentMemOperand(*Op, AccessSize, true /* IsWrite */, RegCtx, Ctx, Out); } @@ -327,7 +345,8 @@ void X86AddressSanitizer::InstrumentMOVSBase(unsigned DstReg, unsigned SrcReg, { const MCExpr *Disp = MCConstantExpr::Create(-1, Ctx); std::unique_ptr<X86Operand> Op(X86Operand::CreateMem( - 0, Disp, DstReg, CntReg, AccessSize, SMLoc(), SMLoc())); + getPointerWidth(), 0, Disp, DstReg, CntReg, AccessSize, SMLoc(), + SMLoc())); InstrumentMemOperand(*Op, AccessSize, true /* IsWrite */, RegCtx, Ctx, Out); } @@ -445,7 +464,8 @@ void X86AddressSanitizer::ComputeMemOperandAddress(X86Operand &Op, const MCConstantExpr *Disp = MCConstantExpr::Create(ApplyDisplacementBounds(Residue), Ctx); std::unique_ptr<X86Operand> DispOp = - X86Operand::CreateMem(0, Disp, Reg, 0, 1, SMLoc(), SMLoc()); + X86Operand::CreateMem(getPointerWidth(), 0, Disp, Reg, 0, 1, SMLoc(), + SMLoc()); EmitLEA(*DispOp, VT, Reg, Out); Residue -= Disp->getValue(); } @@ -459,9 +479,10 @@ X86AddressSanitizer::AddDisplacement(X86Operand &Op, int64_t Displacement, if (Displacement == 0 || (Op.getMemDisp() && Op.getMemDisp()->getKind() != MCExpr::Constant)) { *Residue = Displacement; - return X86Operand::CreateMem(Op.getMemSegReg(), Op.getMemDisp(), - Op.getMemBaseReg(), Op.getMemIndexReg(), - Op.getMemScale(), SMLoc(), SMLoc()); + return X86Operand::CreateMem(Op.getMemModeSize(), Op.getMemSegReg(), + Op.getMemDisp(), Op.getMemBaseReg(), + Op.getMemIndexReg(), Op.getMemScale(), + SMLoc(), SMLoc()); } int64_t OrigDisplacement = @@ -474,9 +495,9 @@ X86AddressSanitizer::AddDisplacement(X86Operand &Op, int64_t Displacement, *Residue = Displacement - NewDisplacement; const MCExpr *Disp = MCConstantExpr::Create(NewDisplacement, Ctx); - return X86Operand::CreateMem(Op.getMemSegReg(), Disp, Op.getMemBaseReg(), - Op.getMemIndexReg(), Op.getMemScale(), SMLoc(), - SMLoc()); + return X86Operand::CreateMem(Op.getMemModeSize(), Op.getMemSegReg(), Disp, + Op.getMemBaseReg(), Op.getMemIndexReg(), + Op.getMemScale(), SMLoc(), SMLoc()); } class X86AddressSanitizer32 : public X86AddressSanitizer { @@ -625,7 +646,8 @@ void X86AddressSanitizer32::InstrumentMemOperandSmall( Inst.addOperand(MCOperand::CreateReg(ShadowRegI8)); const MCExpr *Disp = MCConstantExpr::Create(kShadowOffset, Ctx); std::unique_ptr<X86Operand> Op( - X86Operand::CreateMem(0, Disp, ShadowRegI32, 0, 1, SMLoc(), SMLoc())); + X86Operand::CreateMem(getPointerWidth(), 0, Disp, ShadowRegI32, 0, 1, + SMLoc(), SMLoc())); Op->addMemOperands(Inst, 5); EmitInstruction(Out, Inst); } @@ -634,7 +656,7 @@ void X86AddressSanitizer32::InstrumentMemOperandSmall( Out, MCInstBuilder(X86::TEST8rr).addReg(ShadowRegI8).addReg(ShadowRegI8)); MCSymbol *DoneSym = Ctx.CreateTempSymbol(); const MCExpr *DoneExpr = MCSymbolRefExpr::Create(DoneSym, Ctx); - EmitInstruction(Out, MCInstBuilder(X86::JE_4).addExpr(DoneExpr)); + EmitInstruction(Out, MCInstBuilder(X86::JE_1).addExpr(DoneExpr)); EmitInstruction(Out, MCInstBuilder(X86::MOV32rr).addReg(ScratchRegI32).addReg( AddressRegI32)); @@ -644,12 +666,14 @@ void X86AddressSanitizer32::InstrumentMemOperandSmall( .addImm(7)); switch (AccessSize) { + default: llvm_unreachable("Incorrect access size"); case 1: break; case 2: { const MCExpr *Disp = MCConstantExpr::Create(1, Ctx); std::unique_ptr<X86Operand> Op( - X86Operand::CreateMem(0, Disp, ScratchRegI32, 0, 1, SMLoc(), SMLoc())); + X86Operand::CreateMem(getPointerWidth(), 0, Disp, ScratchRegI32, 0, 1, + SMLoc(), SMLoc())); EmitLEA(*Op, MVT::i32, ScratchRegI32, Out); break; } @@ -659,9 +683,6 @@ void X86AddressSanitizer32::InstrumentMemOperandSmall( .addReg(ScratchRegI32) .addImm(3)); break; - default: - assert(false && "Incorrect access size"); - break; } EmitInstruction( @@ -669,7 +690,7 @@ void X86AddressSanitizer32::InstrumentMemOperandSmall( MCInstBuilder(X86::MOVSX32rr8).addReg(ShadowRegI32).addReg(ShadowRegI8)); EmitInstruction(Out, MCInstBuilder(X86::CMP32rr).addReg(ScratchRegI32).addReg( ShadowRegI32)); - EmitInstruction(Out, MCInstBuilder(X86::JL_4).addExpr(DoneExpr)); + EmitInstruction(Out, MCInstBuilder(X86::JL_1).addExpr(DoneExpr)); EmitCallAsanReport(AccessSize, IsWrite, Ctx, Out, RegCtx); EmitLabel(Out, DoneSym); @@ -692,26 +713,25 @@ void X86AddressSanitizer32::InstrumentMemOperandLarge( { MCInst Inst; switch (AccessSize) { + default: llvm_unreachable("Incorrect access size"); case 8: Inst.setOpcode(X86::CMP8mi); break; case 16: Inst.setOpcode(X86::CMP16mi); break; - default: - assert(false && "Incorrect access size"); - break; } const MCExpr *Disp = MCConstantExpr::Create(kShadowOffset, Ctx); std::unique_ptr<X86Operand> Op( - X86Operand::CreateMem(0, Disp, ShadowRegI32, 0, 1, SMLoc(), SMLoc())); + X86Operand::CreateMem(getPointerWidth(), 0, Disp, ShadowRegI32, 0, 1, + SMLoc(), SMLoc())); Op->addMemOperands(Inst, 5); Inst.addOperand(MCOperand::CreateImm(0)); EmitInstruction(Out, Inst); } MCSymbol *DoneSym = Ctx.CreateTempSymbol(); const MCExpr *DoneExpr = MCSymbolRefExpr::Create(DoneSym, Ctx); - EmitInstruction(Out, MCInstBuilder(X86::JE_4).addExpr(DoneExpr)); + EmitInstruction(Out, MCInstBuilder(X86::JE_1).addExpr(DoneExpr)); EmitCallAsanReport(AccessSize, IsWrite, Ctx, Out, RegCtx); EmitLabel(Out, DoneSym); @@ -727,7 +747,7 @@ void X86AddressSanitizer32::InstrumentMOVSImpl(unsigned AccessSize, const MCExpr *DoneExpr = MCSymbolRefExpr::Create(DoneSym, Ctx); EmitInstruction( Out, MCInstBuilder(X86::TEST32rr).addReg(X86::ECX).addReg(X86::ECX)); - EmitInstruction(Out, MCInstBuilder(X86::JE_4).addExpr(DoneExpr)); + EmitInstruction(Out, MCInstBuilder(X86::JE_1).addExpr(DoneExpr)); // Instrument first and last elements in src and dst range. InstrumentMOVSBase(X86::EDI /* DstReg */, X86::ESI /* SrcReg */, @@ -843,7 +863,8 @@ private: void EmitAdjustRSP(MCContext &Ctx, MCStreamer &Out, long Offset) { const MCExpr *Disp = MCConstantExpr::Create(Offset, Ctx); std::unique_ptr<X86Operand> Op( - X86Operand::CreateMem(0, Disp, X86::RSP, 0, 1, SMLoc(), SMLoc())); + X86Operand::CreateMem(getPointerWidth(), 0, Disp, X86::RSP, 0, 1, + SMLoc(), SMLoc())); EmitLEA(*Op, MVT::i64, X86::RSP, Out); OrigSPOffset += Offset; } @@ -896,7 +917,8 @@ void X86AddressSanitizer64::InstrumentMemOperandSmall( Inst.addOperand(MCOperand::CreateReg(ShadowRegI8)); const MCExpr *Disp = MCConstantExpr::Create(kShadowOffset, Ctx); std::unique_ptr<X86Operand> Op( - X86Operand::CreateMem(0, Disp, ShadowRegI64, 0, 1, SMLoc(), SMLoc())); + X86Operand::CreateMem(getPointerWidth(), 0, Disp, ShadowRegI64, 0, 1, + SMLoc(), SMLoc())); Op->addMemOperands(Inst, 5); EmitInstruction(Out, Inst); } @@ -905,7 +927,7 @@ void X86AddressSanitizer64::InstrumentMemOperandSmall( Out, MCInstBuilder(X86::TEST8rr).addReg(ShadowRegI8).addReg(ShadowRegI8)); MCSymbol *DoneSym = Ctx.CreateTempSymbol(); const MCExpr *DoneExpr = MCSymbolRefExpr::Create(DoneSym, Ctx); - EmitInstruction(Out, MCInstBuilder(X86::JE_4).addExpr(DoneExpr)); + EmitInstruction(Out, MCInstBuilder(X86::JE_1).addExpr(DoneExpr)); EmitInstruction(Out, MCInstBuilder(X86::MOV32rr).addReg(ScratchRegI32).addReg( AddressRegI32)); @@ -915,12 +937,14 @@ void X86AddressSanitizer64::InstrumentMemOperandSmall( .addImm(7)); switch (AccessSize) { + default: llvm_unreachable("Incorrect access size"); case 1: break; case 2: { const MCExpr *Disp = MCConstantExpr::Create(1, Ctx); std::unique_ptr<X86Operand> Op( - X86Operand::CreateMem(0, Disp, ScratchRegI32, 0, 1, SMLoc(), SMLoc())); + X86Operand::CreateMem(getPointerWidth(), 0, Disp, ScratchRegI32, 0, 1, + SMLoc(), SMLoc())); EmitLEA(*Op, MVT::i32, ScratchRegI32, Out); break; } @@ -930,9 +954,6 @@ void X86AddressSanitizer64::InstrumentMemOperandSmall( .addReg(ScratchRegI32) .addImm(3)); break; - default: - assert(false && "Incorrect access size"); - break; } EmitInstruction( @@ -940,7 +961,7 @@ void X86AddressSanitizer64::InstrumentMemOperandSmall( MCInstBuilder(X86::MOVSX32rr8).addReg(ShadowRegI32).addReg(ShadowRegI8)); EmitInstruction(Out, MCInstBuilder(X86::CMP32rr).addReg(ScratchRegI32).addReg( ShadowRegI32)); - EmitInstruction(Out, MCInstBuilder(X86::JL_4).addExpr(DoneExpr)); + EmitInstruction(Out, MCInstBuilder(X86::JL_1).addExpr(DoneExpr)); EmitCallAsanReport(AccessSize, IsWrite, Ctx, Out, RegCtx); EmitLabel(Out, DoneSym); @@ -963,19 +984,18 @@ void X86AddressSanitizer64::InstrumentMemOperandLarge( { MCInst Inst; switch (AccessSize) { + default: llvm_unreachable("Incorrect access size"); case 8: Inst.setOpcode(X86::CMP8mi); break; case 16: Inst.setOpcode(X86::CMP16mi); break; - default: - assert(false && "Incorrect access size"); - break; } const MCExpr *Disp = MCConstantExpr::Create(kShadowOffset, Ctx); std::unique_ptr<X86Operand> Op( - X86Operand::CreateMem(0, Disp, ShadowRegI64, 0, 1, SMLoc(), SMLoc())); + X86Operand::CreateMem(getPointerWidth(), 0, Disp, ShadowRegI64, 0, 1, + SMLoc(), SMLoc())); Op->addMemOperands(Inst, 5); Inst.addOperand(MCOperand::CreateImm(0)); EmitInstruction(Out, Inst); @@ -983,7 +1003,7 @@ void X86AddressSanitizer64::InstrumentMemOperandLarge( MCSymbol *DoneSym = Ctx.CreateTempSymbol(); const MCExpr *DoneExpr = MCSymbolRefExpr::Create(DoneSym, Ctx); - EmitInstruction(Out, MCInstBuilder(X86::JE_4).addExpr(DoneExpr)); + EmitInstruction(Out, MCInstBuilder(X86::JE_1).addExpr(DoneExpr)); EmitCallAsanReport(AccessSize, IsWrite, Ctx, Out, RegCtx); EmitLabel(Out, DoneSym); @@ -999,7 +1019,7 @@ void X86AddressSanitizer64::InstrumentMOVSImpl(unsigned AccessSize, const MCExpr *DoneExpr = MCSymbolRefExpr::Create(DoneSym, Ctx); EmitInstruction( Out, MCInstBuilder(X86::TEST64rr).addReg(X86::RCX).addReg(X86::RCX)); - EmitInstruction(Out, MCInstBuilder(X86::JE_4).addExpr(DoneExpr)); + EmitInstruction(Out, MCInstBuilder(X86::JE_1).addExpr(DoneExpr)); // Instrument first and last elements in src and dst range. InstrumentMOVSBase(X86::RDI /* DstReg */, X86::RSI /* SrcReg */, diff --git a/lib/Target/X86/AsmParser/X86AsmParser.cpp b/lib/Target/X86/AsmParser/X86AsmParser.cpp index 8ef2a55..0b6fb52 100644 --- a/lib/Target/X86/AsmParser/X86AsmParser.cpp +++ b/lib/Target/X86/AsmParser/X86AsmParser.cpp @@ -86,7 +86,7 @@ private: typedef std::pair< InfixCalculatorTok, int64_t > ICToken; SmallVector<InfixCalculatorTok, 4> InfixOperatorStack; SmallVector<ICToken, 4> PostfixStack; - + public: int64_t popOperand() { assert (!PostfixStack.empty() && "Poped an empty stack!"); @@ -100,7 +100,7 @@ private: "Unexpected operand!"); PostfixStack.push_back(std::make_pair(Op, Val)); } - + void popOperator() { InfixOperatorStack.pop_back(); } void pushOperator(InfixCalculatorTok Op) { // Push the new operator if the stack is empty. @@ -108,7 +108,7 @@ private: InfixOperatorStack.push_back(Op); return; } - + // Push the new operator if it has a higher precedence than the operator // on the top of the stack or the operator on the top of the stack is a // left parentheses. @@ -118,7 +118,7 @@ private: InfixOperatorStack.push_back(Op); return; } - + // The operator on the top of the stack has higher precedence than the // new operator. unsigned ParenCount = 0; @@ -126,17 +126,17 @@ private: // Nothing to process. if (InfixOperatorStack.empty()) break; - + Idx = InfixOperatorStack.size() - 1; StackOp = InfixOperatorStack[Idx]; if (!(OpPrecedence[StackOp] >= OpPrecedence[Op] || ParenCount)) break; - + // If we have an even parentheses count and we see a left parentheses, // then stop processing. if (!ParenCount && StackOp == IC_LPAREN) break; - + if (StackOp == IC_RPAREN) { ++ParenCount; InfixOperatorStack.pop_back(); @@ -158,10 +158,10 @@ private: if (StackOp != IC_LPAREN && StackOp != IC_RPAREN) PostfixStack.push_back(std::make_pair(StackOp, 0)); } - + if (PostfixStack.empty()) return 0; - + SmallVector<ICToken, 16> OperandStack; for (unsigned i = 0, e = PostfixStack.size(); i != e; ++i) { ICToken Op = PostfixStack[i]; @@ -263,7 +263,7 @@ private: State(IES_PLUS), PrevState(IES_ERROR), BaseReg(0), IndexReg(0), TmpReg(0), Scale(1), Imm(imm), Sym(nullptr), StopOnLBrac(stoponlbrac), AddImmPrefix(addimmprefix) { Info.clear(); } - + unsigned getBaseReg() { return BaseReg; } unsigned getIndexReg() { return IndexReg; } unsigned getScale() { return Scale; } @@ -684,6 +684,7 @@ private: bool ParseDirectiveWord(unsigned Size, SMLoc L); bool ParseDirectiveCode(StringRef IDVal, SMLoc L); + bool validateInstruction(MCInst &Inst, const OperandVector &Ops); bool processInstruction(MCInst &Inst, const OperandVector &Ops); /// Wrapper around MCStreamer::EmitInstruction(). Possibly adds @@ -711,13 +712,6 @@ private: uint64_t &ErrorInfo, bool MatchingInlineAsm); - unsigned getPointerSize() { - if (is16BitMode()) return 16; - if (is32BitMode()) return 32; - if (is64BitMode()) return 64; - llvm_unreachable("invalid mode"); - } - bool OmitRegisterFromClobberLists(unsigned RegNo) override; /// doSrcDstMatch - Returns true if operands are matching in their @@ -977,16 +971,18 @@ std::unique_ptr<X86Operand> X86AsmParser::DefaultMemSIOperand(SMLoc Loc) { unsigned basereg = is64BitMode() ? X86::RSI : (is32BitMode() ? X86::ESI : X86::SI); const MCExpr *Disp = MCConstantExpr::Create(0, getContext()); - return X86Operand::CreateMem(/*SegReg=*/0, Disp, /*BaseReg=*/basereg, - /*IndexReg=*/0, /*Scale=*/1, Loc, Loc, 0); + return X86Operand::CreateMem(getPointerWidth(), /*SegReg=*/0, Disp, + /*BaseReg=*/basereg, /*IndexReg=*/0, /*Scale=*/1, + Loc, Loc, 0); } std::unique_ptr<X86Operand> X86AsmParser::DefaultMemDIOperand(SMLoc Loc) { unsigned basereg = is64BitMode() ? X86::RDI : (is32BitMode() ? X86::EDI : X86::DI); const MCExpr *Disp = MCConstantExpr::Create(0, getContext()); - return X86Operand::CreateMem(/*SegReg=*/0, Disp, /*BaseReg=*/basereg, - /*IndexReg=*/0, /*Scale=*/1, Loc, Loc, 0); + return X86Operand::CreateMem(getPointerWidth(), /*SegReg=*/0, Disp, + /*BaseReg=*/basereg, /*IndexReg=*/0, /*Scale=*/1, + Loc, Loc, 0); } std::unique_ptr<X86Operand> X86AsmParser::ParseOperand() { @@ -1027,8 +1023,8 @@ std::unique_ptr<X86Operand> X86AsmParser::CreateMemForInlineAsm( // Create an absolute memory reference in order to match against // instructions taking a PC relative operand. - return X86Operand::CreateMem(Disp, Start, End, Size, Identifier, - Info.OpDecl); + return X86Operand::CreateMem(getPointerWidth(), Disp, Start, End, Size, + Identifier, Info.OpDecl); } // We either have a direct symbol reference, or an offset from a symbol. The @@ -1050,8 +1046,9 @@ std::unique_ptr<X86Operand> X86AsmParser::CreateMemForInlineAsm( // if we don't know the actual value at this time. This is necessary to // get the matching correct in some cases. BaseReg = BaseReg ? BaseReg : 1; - return X86Operand::CreateMem(SegReg, Disp, BaseReg, IndexReg, Scale, Start, - End, Size, Identifier, Info.OpDecl); + return X86Operand::CreateMem(getPointerWidth(), SegReg, Disp, BaseReg, + IndexReg, Scale, Start, End, Size, Identifier, + Info.OpDecl); } static void @@ -1103,7 +1100,7 @@ RewriteIntelBracExpression(SmallVectorImpl<AsmRewrite> *AsmRewrites, (*I).Kind = AOK_Delete; } const char *SymLocPtr = SymName.data(); - // Skip everything before the symbol. + // Skip everything before the symbol. if (unsigned Len = SymLocPtr - StartInBrac.getPointer()) { assert(Len > 0 && "Expected a non-negative length."); AsmRewrites->push_back(AsmRewrite(AOK_Skip, StartInBrac, Len)); @@ -1128,7 +1125,7 @@ bool X86AsmParser::ParseIntelExpression(IntelExprStateMachine &SM, SMLoc &End) { // identifier. Don't try an parse it as a register. if (Tok.getString().startswith(".")) break; - + // If we're parsing an immediate expression, we don't expect a '['. if (SM.getStopOnLBrac() && getLexer().getKind() == AsmToken::LBrac) break; @@ -1194,7 +1191,7 @@ bool X86AsmParser::ParseIntelExpression(IntelExprStateMachine &SM, SMLoc &End) { MCSymbol *Sym = getContext().GetDirectionalLocalSymbol(IntVal, IDVal == "b"); MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None; - const MCExpr *Val = + const MCExpr *Val = MCSymbolRefExpr::Create(Sym, Variant, getContext()); if (IDVal == "b" && Sym->isUndefined()) return Error(Loc, "invalid reference to undefined symbol"); @@ -1279,7 +1276,7 @@ X86AsmParser::ParseIntelBracExpression(unsigned SegReg, SMLoc Start, const MCExpr *NewDisp; if (ParseIntelDotOperator(Disp, NewDisp)) return nullptr; - + End = Tok.getEndLoc(); Parser.Lex(); // Eat the field. Disp = NewDisp; @@ -1292,17 +1289,17 @@ X86AsmParser::ParseIntelBracExpression(unsigned SegReg, SMLoc Start, // handle [-42] if (!BaseReg && !IndexReg) { if (!SegReg) - return X86Operand::CreateMem(Disp, Start, End, Size); - else - return X86Operand::CreateMem(SegReg, Disp, 0, 0, 1, Start, End, Size); + return X86Operand::CreateMem(getPointerWidth(), Disp, Start, End, Size); + return X86Operand::CreateMem(getPointerWidth(), SegReg, Disp, 0, 0, 1, + Start, End, Size); } StringRef ErrMsg; if (CheckBaseRegAndIndexReg(BaseReg, IndexReg, ErrMsg)) { Error(StartInBrac, ErrMsg); return nullptr; } - return X86Operand::CreateMem(SegReg, Disp, BaseReg, IndexReg, Scale, Start, - End, Size); + return X86Operand::CreateMem(getPointerWidth(), SegReg, Disp, BaseReg, + IndexReg, Scale, Start, End, Size); } InlineAsmIdentifierInfo &Info = SM.getIdentifierInfo(); @@ -1383,9 +1380,9 @@ X86AsmParser::ParseIntelSegmentOverride(unsigned SegReg, SMLoc Start, // be followed by a bracketed expression. If it isn't we know we have our // final segment override. const MCExpr *Disp = MCConstantExpr::Create(ImmDisp, getContext()); - return X86Operand::CreateMem(SegReg, Disp, /*BaseReg=*/0, /*IndexReg=*/0, - /*Scale=*/1, Start, ImmDispToken.getEndLoc(), - Size); + return X86Operand::CreateMem(getPointerWidth(), SegReg, Disp, + /*BaseReg=*/0, /*IndexReg=*/0, /*Scale=*/1, + Start, ImmDispToken.getEndLoc(), Size); } } @@ -1398,7 +1395,7 @@ X86AsmParser::ParseIntelSegmentOverride(unsigned SegReg, SMLoc Start, if (getParser().parsePrimaryExpr(Val, End)) return ErrorOperand(Tok.getLoc(), "unknown token in expression"); - return X86Operand::CreateMem(Val, Start, End, Size); + return X86Operand::CreateMem(getPointerWidth(), Val, Start, End, Size); } InlineAsmIdentifierInfo Info; @@ -1428,7 +1425,7 @@ std::unique_ptr<X86Operand> X86AsmParser::ParseIntelMemOperand(int64_t ImmDisp, if (getParser().parsePrimaryExpr(Val, End)) return ErrorOperand(Tok.getLoc(), "unknown token in expression"); - return X86Operand::CreateMem(Val, Start, End, Size); + return X86Operand::CreateMem(getPointerWidth(), Val, Start, End, Size); } InlineAsmIdentifierInfo Info; @@ -1466,9 +1463,9 @@ std::unique_ptr<X86Operand> X86AsmParser::ParseIntelMemOperand(int64_t ImmDisp, // BaseReg is non-zero to avoid assertions. In the context of inline asm, // we're pointing to a local variable in memory, so the base register is // really the frame or stack pointer. - return X86Operand::CreateMem(/*SegReg=*/0, Disp, /*BaseReg=*/1, /*IndexReg=*/0, - /*Scale=*/1, Start, End, Size, Identifier, - Info.OpDecl); + return X86Operand::CreateMem(getPointerWidth(), /*SegReg=*/0, Disp, + /*BaseReg=*/1, /*IndexReg=*/0, /*Scale=*/1, + Start, End, Size, Identifier, Info.OpDecl); } /// Parse the '.' operator. @@ -1643,7 +1640,8 @@ std::unique_ptr<X86Operand> X86AsmParser::ParseIntelOperand() { // to the MCExpr with the directional local symbol and this is a // memory operand not an immediate operand. if (SM.getSym()) - return X86Operand::CreateMem(SM.getSym(), Start, End, Size); + return X86Operand::CreateMem(getPointerWidth(), SM.getSym(), Start, End, + Size); const MCExpr *ImmExpr = MCConstantExpr::Create(Imm, getContext()); return X86Operand::CreateImm(ImmExpr, Start, End); @@ -1802,8 +1800,9 @@ std::unique_ptr<X86Operand> X86AsmParser::ParseMemOperand(unsigned SegReg, if (getLexer().isNot(AsmToken::LParen)) { // Unless we have a segment register, treat this as an immediate. if (SegReg == 0) - return X86Operand::CreateMem(Disp, MemStart, ExprEnd); - return X86Operand::CreateMem(SegReg, Disp, 0, 0, 1, MemStart, ExprEnd); + return X86Operand::CreateMem(getPointerWidth(), Disp, MemStart, ExprEnd); + return X86Operand::CreateMem(getPointerWidth(), SegReg, Disp, 0, 0, 1, + MemStart, ExprEnd); } // Eat the '('. @@ -1829,8 +1828,10 @@ std::unique_ptr<X86Operand> X86AsmParser::ParseMemOperand(unsigned SegReg, if (getLexer().isNot(AsmToken::LParen)) { // Unless we have a segment register, treat this as an immediate. if (SegReg == 0) - return X86Operand::CreateMem(Disp, LParenLoc, ExprEnd); - return X86Operand::CreateMem(SegReg, Disp, 0, 0, 1, MemStart, ExprEnd); + return X86Operand::CreateMem(getPointerWidth(), Disp, LParenLoc, + ExprEnd); + return X86Operand::CreateMem(getPointerWidth(), SegReg, Disp, 0, 0, 1, + MemStart, ExprEnd); } // Eat the '('. @@ -1946,9 +1947,9 @@ std::unique_ptr<X86Operand> X86AsmParser::ParseMemOperand(unsigned SegReg, } if (SegReg || BaseReg || IndexReg) - return X86Operand::CreateMem(SegReg, Disp, BaseReg, IndexReg, Scale, - MemStart, MemEnd); - return X86Operand::CreateMem(Disp, MemStart, MemEnd); + return X86Operand::CreateMem(getPointerWidth(), SegReg, Disp, BaseReg, + IndexReg, Scale, MemStart, MemEnd); + return X86Operand::CreateMem(getPointerWidth(), Disp, MemStart, MemEnd); } bool X86AsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, @@ -1963,14 +1964,13 @@ bool X86AsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, PatchedName = PatchedName.substr(0, Name.size()-1); // FIXME: Hack to recognize cmp<comparison code>{ss,sd,ps,pd}. - const MCExpr *ExtraImmOp = nullptr; if ((PatchedName.startswith("cmp") || PatchedName.startswith("vcmp")) && (PatchedName.endswith("ss") || PatchedName.endswith("sd") || PatchedName.endswith("ps") || PatchedName.endswith("pd"))) { bool IsVCMP = PatchedName[0] == 'v'; - unsigned SSECCIdx = IsVCMP ? 4 : 3; - unsigned SSEComparisonCode = StringSwitch<unsigned>( - PatchedName.slice(SSECCIdx, PatchedName.size() - 2)) + unsigned CCIdx = IsVCMP ? 4 : 3; + unsigned ComparisonCode = StringSwitch<unsigned>( + PatchedName.slice(CCIdx, PatchedName.size() - 2)) .Case("eq", 0x00) .Case("lt", 0x01) .Case("le", 0x02) @@ -2005,27 +2005,75 @@ bool X86AsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, .Case("gt_oq", 0x1E) .Case("true_us", 0x1F) .Default(~0U); - if (SSEComparisonCode != ~0U && (IsVCMP || SSEComparisonCode < 8)) { - ExtraImmOp = MCConstantExpr::Create(SSEComparisonCode, - getParser().getContext()); - if (PatchedName.endswith("ss")) { - PatchedName = IsVCMP ? "vcmpss" : "cmpss"; - } else if (PatchedName.endswith("sd")) { - PatchedName = IsVCMP ? "vcmpsd" : "cmpsd"; - } else if (PatchedName.endswith("ps")) { - PatchedName = IsVCMP ? "vcmpps" : "cmpps"; - } else { - assert(PatchedName.endswith("pd") && "Unexpected mnemonic!"); - PatchedName = IsVCMP ? "vcmppd" : "cmppd"; - } + if (ComparisonCode != ~0U && (IsVCMP || ComparisonCode < 8)) { + + Operands.push_back(X86Operand::CreateToken(PatchedName.slice(0, CCIdx), + NameLoc)); + + const MCExpr *ImmOp = MCConstantExpr::Create(ComparisonCode, + getParser().getContext()); + Operands.push_back(X86Operand::CreateImm(ImmOp, NameLoc, NameLoc)); + + PatchedName = PatchedName.substr(PatchedName.size() - 2); + } + } + + // FIXME: Hack to recognize vpcmp<comparison code>{ub,uw,ud,uq,b,w,d,q}. + if (PatchedName.startswith("vpcmp") && + (PatchedName.endswith("b") || PatchedName.endswith("w") || + PatchedName.endswith("d") || PatchedName.endswith("q"))) { + unsigned CCIdx = PatchedName.drop_back().back() == 'u' ? 2 : 1; + unsigned ComparisonCode = StringSwitch<unsigned>( + PatchedName.slice(5, PatchedName.size() - CCIdx)) + .Case("eq", 0x0) // Only allowed on unsigned. Checked below. + .Case("lt", 0x1) + .Case("le", 0x2) + //.Case("false", 0x3) // Not a documented alias. + .Case("neq", 0x4) + .Case("nlt", 0x5) + .Case("nle", 0x6) + //.Case("true", 0x7) // Not a documented alias. + .Default(~0U); + if (ComparisonCode != ~0U && (ComparisonCode != 0 || CCIdx == 2)) { + Operands.push_back(X86Operand::CreateToken("vpcmp", NameLoc)); + + const MCExpr *ImmOp = MCConstantExpr::Create(ComparisonCode, + getParser().getContext()); + Operands.push_back(X86Operand::CreateImm(ImmOp, NameLoc, NameLoc)); + + PatchedName = PatchedName.substr(PatchedName.size() - CCIdx); + } + } + + // FIXME: Hack to recognize vpcom<comparison code>{ub,uw,ud,uq,b,w,d,q}. + if (PatchedName.startswith("vpcom") && + (PatchedName.endswith("b") || PatchedName.endswith("w") || + PatchedName.endswith("d") || PatchedName.endswith("q"))) { + unsigned CCIdx = PatchedName.drop_back().back() == 'u' ? 2 : 1; + unsigned ComparisonCode = StringSwitch<unsigned>( + PatchedName.slice(5, PatchedName.size() - CCIdx)) + .Case("lt", 0x0) + .Case("le", 0x1) + .Case("gt", 0x2) + .Case("ge", 0x3) + .Case("eq", 0x4) + .Case("neq", 0x5) + .Case("false", 0x6) + .Case("true", 0x7) + .Default(~0U); + if (ComparisonCode != ~0U) { + Operands.push_back(X86Operand::CreateToken("vpcom", NameLoc)); + + const MCExpr *ImmOp = MCConstantExpr::Create(ComparisonCode, + getParser().getContext()); + Operands.push_back(X86Operand::CreateImm(ImmOp, NameLoc, NameLoc)); + + PatchedName = PatchedName.substr(PatchedName.size() - CCIdx); } } Operands.push_back(X86Operand::CreateToken(PatchedName, NameLoc)); - if (ExtraImmOp && !isParsingIntelSyntax()) - Operands.push_back(X86Operand::CreateImm(ExtraImmOp, NameLoc, NameLoc)); - // Determine whether this is an instruction prefix. bool isPrefix = Name == "lock" || Name == "rep" || @@ -2071,9 +2119,6 @@ bool X86AsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, (isPrefix && getLexer().is(AsmToken::Slash))) Parser.Lex(); - if (ExtraImmOp && isParsingIntelSyntax()) - Operands.push_back(X86Operand::CreateImm(ExtraImmOp, NameLoc, NameLoc)); - // This is a terrible hack to handle "out[bwl]? %al, (%dx)" -> // "outb %al, %dx". Out doesn't take a memory form, but this is a widely // documented form in various unofficial manuals, so a lot of code uses it. @@ -2272,6 +2317,22 @@ static bool convert64i32to64ri8(MCInst &Inst, unsigned Opcode, return convertToSExti8(Inst, Opcode, X86::RAX, isCmp); } +bool X86AsmParser::validateInstruction(MCInst &Inst, const OperandVector &Ops) { + switch (Inst.getOpcode()) { + default: return true; + case X86::INT: + X86Operand &Op = static_cast<X86Operand &>(*Ops[1]); + assert(Op.isImm() && "expected immediate"); + int64_t Res; + if (!Op.getImm()->EvaluateAsAbsolute(Res) || Res > 255) { + Error(Op.getStartLoc(), "interrupt vector must be in range [0-255]"); + return false; + } + return true; + } + llvm_unreachable("handle the instruction appropriately"); +} + bool X86AsmParser::processInstruction(MCInst &Inst, const OperandVector &Ops) { switch (Inst.getOpcode()) { default: return false; @@ -2432,8 +2493,11 @@ bool X86AsmParser::MatchAndEmitATTInstruction(SMLoc IDLoc, unsigned &Opcode, switch (MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, isParsingIntelSyntax())) { - default: break; + default: llvm_unreachable("Unexpected match result!"); case Match_Success: + if (!validateInstruction(Inst, Operands)) + return true; + // Some instructions need post-processing to, for example, tweak which // encoding is selected. Loop on it while changes happen so the // individual transformations can chain off each other. @@ -2614,7 +2678,7 @@ bool X86AsmParser::MatchAndEmitIntelInstruction(SMLoc IDLoc, unsigned &Opcode, static const char *const PtrSizedInstrs[] = {"call", "jmp", "push"}; for (const char *Instr : PtrSizedInstrs) { if (Mnemonic == Instr) { - UnsizedMemOp->Mem.Size = getPointerSize(); + UnsizedMemOp->Mem.Size = getPointerWidth(); break; } } @@ -2626,7 +2690,7 @@ bool X86AsmParser::MatchAndEmitIntelInstruction(SMLoc IDLoc, unsigned &Opcode, SmallVector<unsigned, 8> Match; uint64_t ErrorInfoMissingFeature = 0; if (UnsizedMemOp && UnsizedMemOp->isMemUnsized()) { - static const unsigned MopSizes[] = {8, 16, 32, 64, 80}; + static const unsigned MopSizes[] = {8, 16, 32, 64, 80, 128, 256, 512}; for (unsigned Size : MopSizes) { UnsizedMemOp->Mem.Size = Size; uint64_t ErrorInfoIgnore; @@ -2648,7 +2712,7 @@ bool X86AsmParser::MatchAndEmitIntelInstruction(SMLoc IDLoc, unsigned &Opcode, } // If we haven't matched anything yet, this is not a basic integer or FPU - // operation. There shouldn't be any ambiguity in our mneumonic table, so try + // operation. There shouldn't be any ambiguity in our mnemonic table, so try // matching with the unsized operand. if (Match.empty()) { Match.push_back(MatchInstructionImpl(Operands, Inst, ErrorInfo, @@ -2677,6 +2741,9 @@ bool X86AsmParser::MatchAndEmitIntelInstruction(SMLoc IDLoc, unsigned &Opcode, unsigned NumSuccessfulMatches = std::count(std::begin(Match), std::end(Match), Match_Success); if (NumSuccessfulMatches == 1) { + if (!validateInstruction(Inst, Operands)) + return true; + // Some instructions need post-processing to, for example, tweak which // encoding is selected. Loop on it while changes happen so the individual // transformations can chain off each other. diff --git a/lib/Target/X86/AsmParser/X86AsmParserCommon.h b/lib/Target/X86/AsmParser/X86AsmParserCommon.h index 72aeeaa..7610806 100644 --- a/lib/Target/X86/AsmParser/X86AsmParserCommon.h +++ b/lib/Target/X86/AsmParser/X86AsmParserCommon.h @@ -34,6 +34,11 @@ inline bool isImmSExti64i32Value(uint64_t Value) { (0xFFFFFFFF80000000ULL <= Value && Value <= 0xFFFFFFFFFFFFFFFFULL)); } +inline bool isImmUnsignedi8Value(uint64_t Value) { + return (( Value <= 0x00000000000000FFULL)|| + (0xFFFFFFFFFFFFFF80ULL <= Value && Value <= 0xFFFFFFFFFFFFFFFFULL)); +} + } // End of namespace llvm #endif diff --git a/lib/Target/X86/AsmParser/X86Operand.h b/lib/Target/X86/AsmParser/X86Operand.h index e0fab8d..d67e119 100644 --- a/lib/Target/X86/AsmParser/X86Operand.h +++ b/lib/Target/X86/AsmParser/X86Operand.h @@ -53,6 +53,7 @@ struct X86Operand : public MCParsedAsmOperand { unsigned IndexReg; unsigned Scale; unsigned Size; + unsigned ModeSize; }; union { @@ -120,6 +121,10 @@ struct X86Operand : public MCParsedAsmOperand { assert(Kind == Memory && "Invalid access!"); return Mem.Scale; } + unsigned getMemModeSize() const { + assert(Kind == Memory && "Invalid access!"); + return Mem.ModeSize; + } bool isToken() const override {return Kind == Token; } @@ -182,6 +187,13 @@ struct X86Operand : public MCParsedAsmOperand { return isImmSExti64i32Value(CE->getValue()); } + bool isImmUnsignedi8() const { + if (!isImm()) return false; + const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); + if (!CE) return false; + return isImmUnsignedi8Value(CE->getValue()); + } + bool isOffsetOf() const override { return OffsetOfLoc.getPointer(); } @@ -249,6 +261,10 @@ struct X86Operand : public MCParsedAsmOperand { !getMemIndexReg() && getMemScale() == 1; } + bool isAbsMem16() const { + return isAbsMem() && Mem.ModeSize == 16; + } + bool isSrcIdx() const { return !getMemIndexReg() && getMemScale() == 1 && (getMemBaseReg() == X86::RSI || getMemBaseReg() == X86::ESI || @@ -288,21 +304,43 @@ struct X86Operand : public MCParsedAsmOperand { return isMem64() && isDstIdx(); } - bool isMemOffs8() const { - return Kind == Memory && !getMemBaseReg() && - !getMemIndexReg() && getMemScale() == 1 && (!Mem.Size || Mem.Size == 8); + bool isMemOffs() const { + return Kind == Memory && !getMemBaseReg() && !getMemIndexReg() && + getMemScale() == 1; + } + + bool isMemOffs16_8() const { + return isMemOffs() && Mem.ModeSize == 16 && (!Mem.Size || Mem.Size == 8); + } + bool isMemOffs16_16() const { + return isMemOffs() && Mem.ModeSize == 16 && (!Mem.Size || Mem.Size == 16); } - bool isMemOffs16() const { - return Kind == Memory && !getMemBaseReg() && - !getMemIndexReg() && getMemScale() == 1 && (!Mem.Size || Mem.Size == 16); + bool isMemOffs16_32() const { + return isMemOffs() && Mem.ModeSize == 16 && (!Mem.Size || Mem.Size == 32); } - bool isMemOffs32() const { - return Kind == Memory && !getMemBaseReg() && - !getMemIndexReg() && getMemScale() == 1 && (!Mem.Size || Mem.Size == 32); + bool isMemOffs32_8() const { + return isMemOffs() && Mem.ModeSize == 32 && (!Mem.Size || Mem.Size == 8); } - bool isMemOffs64() const { - return Kind == Memory && !getMemBaseReg() && - !getMemIndexReg() && getMemScale() == 1 && (!Mem.Size || Mem.Size == 64); + bool isMemOffs32_16() const { + return isMemOffs() && Mem.ModeSize == 32 && (!Mem.Size || Mem.Size == 16); + } + bool isMemOffs32_32() const { + return isMemOffs() && Mem.ModeSize == 32 && (!Mem.Size || Mem.Size == 32); + } + bool isMemOffs32_64() const { + return isMemOffs() && Mem.ModeSize == 32 && (!Mem.Size || Mem.Size == 64); + } + bool isMemOffs64_8() const { + return isMemOffs() && Mem.ModeSize == 64 && (!Mem.Size || Mem.Size == 8); + } + bool isMemOffs64_16() const { + return isMemOffs() && Mem.ModeSize == 64 && (!Mem.Size || Mem.Size == 16); + } + bool isMemOffs64_32() const { + return isMemOffs() && Mem.ModeSize == 64 && (!Mem.Size || Mem.Size == 32); + } + bool isMemOffs64_64() const { + return isMemOffs() && Mem.ModeSize == 64 && (!Mem.Size || Mem.Size == 64); } bool isReg() const override { return Kind == Register; } @@ -430,8 +468,9 @@ struct X86Operand : public MCParsedAsmOperand { /// Create an absolute memory operand. static std::unique_ptr<X86Operand> - CreateMem(const MCExpr *Disp, SMLoc StartLoc, SMLoc EndLoc, unsigned Size = 0, - StringRef SymName = StringRef(), void *OpDecl = nullptr) { + CreateMem(unsigned ModeSize, const MCExpr *Disp, SMLoc StartLoc, SMLoc EndLoc, + unsigned Size = 0, StringRef SymName = StringRef(), + void *OpDecl = nullptr) { auto Res = llvm::make_unique<X86Operand>(Memory, StartLoc, EndLoc); Res->Mem.SegReg = 0; Res->Mem.Disp = Disp; @@ -439,6 +478,7 @@ struct X86Operand : public MCParsedAsmOperand { Res->Mem.IndexReg = 0; Res->Mem.Scale = 1; Res->Mem.Size = Size; + Res->Mem.ModeSize = ModeSize; Res->SymName = SymName; Res->OpDecl = OpDecl; Res->AddressOf = false; @@ -447,9 +487,9 @@ struct X86Operand : public MCParsedAsmOperand { /// Create a generalized memory operand. static std::unique_ptr<X86Operand> - CreateMem(unsigned SegReg, const MCExpr *Disp, unsigned BaseReg, - unsigned IndexReg, unsigned Scale, SMLoc StartLoc, SMLoc EndLoc, - unsigned Size = 0, StringRef SymName = StringRef(), + CreateMem(unsigned ModeSize, unsigned SegReg, const MCExpr *Disp, + unsigned BaseReg, unsigned IndexReg, unsigned Scale, SMLoc StartLoc, + SMLoc EndLoc, unsigned Size = 0, StringRef SymName = StringRef(), void *OpDecl = nullptr) { // We should never just have a displacement, that should be parsed as an // absolute memory operand. @@ -465,6 +505,7 @@ struct X86Operand : public MCParsedAsmOperand { Res->Mem.IndexReg = IndexReg; Res->Mem.Scale = Scale; Res->Mem.Size = Size; + Res->Mem.ModeSize = ModeSize; Res->SymName = SymName; Res->OpDecl = OpDecl; Res->AddressOf = false; |