diff options
Diffstat (limited to 'lib/CodeGen/MachineVerifier.cpp')
-rw-r--r-- | lib/CodeGen/MachineVerifier.cpp | 510 |
1 files changed, 403 insertions, 107 deletions
diff --git a/lib/CodeGen/MachineVerifier.cpp b/lib/CodeGen/MachineVerifier.cpp index 534d3699db29..0ad792ac62cf 100644 --- a/lib/CodeGen/MachineVerifier.cpp +++ b/lib/CodeGen/MachineVerifier.cpp @@ -1,9 +1,8 @@ //===- MachineVerifier.cpp - Machine Code Verifier ------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -219,7 +218,7 @@ namespace { bool isAllocatable(unsigned Reg) const { return Reg < TRI->getNumRegs() && TRI->isInAllocatableClass(Reg) && - !regsReserved.test(Reg); + !regsReserved.test(Reg); } // Analysis information if available @@ -231,6 +230,9 @@ namespace { void visitMachineFunctionBefore(); void visitMachineBasicBlockBefore(const MachineBasicBlock *MBB); void visitMachineBundleBefore(const MachineInstr *MI); + + bool verifyVectorElementMatch(LLT Ty0, LLT Ty1, const MachineInstr *MI); + void verifyPreISelGenericInstruction(const MachineInstr *MI); void visitMachineInstrBefore(const MachineInstr *MI); void visitMachineOperand(const MachineOperand *MO, unsigned MONum); void visitMachineInstrAfter(const MachineInstr *MI); @@ -838,7 +840,7 @@ void MachineVerifier::visitMachineBundleBefore(const MachineInstr *MI) { if (MI->isTerminator() && !TII->isPredicated(*MI)) { if (!FirstTerminator) FirstTerminator = MI; - } else if (FirstTerminator) { + } else if (FirstTerminator && !MI->isDebugEntryValue()) { report("Non-terminator instruction after the first terminator", MI); errs() << "First terminator was:\t" << *FirstTerminator; } @@ -889,109 +891,150 @@ void MachineVerifier::verifyInlineAsm(const MachineInstr *MI) { } } -void MachineVerifier::visitMachineInstrBefore(const MachineInstr *MI) { - const MCInstrDesc &MCID = MI->getDesc(); - if (MI->getNumOperands() < MCID.getNumOperands()) { - report("Too few operands", MI); - errs() << MCID.getNumOperands() << " operands expected, but " - << MI->getNumOperands() << " given.\n"; +/// Check that types are consistent when two operands need to have the same +/// number of vector elements. +/// \return true if the types are valid. +bool MachineVerifier::verifyVectorElementMatch(LLT Ty0, LLT Ty1, + const MachineInstr *MI) { + if (Ty0.isVector() != Ty1.isVector()) { + report("operand types must be all-vector or all-scalar", MI); + // Generally we try to report as many issues as possible at once, but in + // this case it's not clear what should we be comparing the size of the + // scalar with: the size of the whole vector or its lane. Instead of + // making an arbitrary choice and emitting not so helpful message, let's + // avoid the extra noise and stop here. + return false; } - if (MI->isPHI()) { - if (MF->getProperties().hasProperty( - MachineFunctionProperties::Property::NoPHIs)) - report("Found PHI instruction with NoPHIs property set", MI); + if (Ty0.isVector() && Ty0.getNumElements() != Ty1.getNumElements()) { + report("operand types must preserve number of vector elements", MI); + return false; + } - if (FirstNonPHI) - report("Found PHI instruction after non-PHI", MI); - } else if (FirstNonPHI == nullptr) - FirstNonPHI = MI; + return true; +} - // Check the tied operands. - if (MI->isInlineAsm()) - verifyInlineAsm(MI); +void MachineVerifier::verifyPreISelGenericInstruction(const MachineInstr *MI) { + if (isFunctionSelected) + report("Unexpected generic instruction in a Selected function", MI); - // Check the MachineMemOperands for basic consistency. - for (MachineInstr::mmo_iterator I = MI->memoperands_begin(), - E = MI->memoperands_end(); + const MCInstrDesc &MCID = MI->getDesc(); + unsigned NumOps = MI->getNumOperands(); + + // Check types. + SmallVector<LLT, 4> Types; + for (unsigned I = 0, E = std::min(MCID.getNumOperands(), NumOps); I != E; ++I) { - if ((*I)->isLoad() && !MI->mayLoad()) - report("Missing mayLoad flag", MI); - if ((*I)->isStore() && !MI->mayStore()) - report("Missing mayStore flag", MI); - } + if (!MCID.OpInfo[I].isGenericType()) + continue; + // Generic instructions specify type equality constraints between some of + // their operands. Make sure these are consistent. + size_t TypeIdx = MCID.OpInfo[I].getGenericTypeIndex(); + Types.resize(std::max(TypeIdx + 1, Types.size())); + + const MachineOperand *MO = &MI->getOperand(I); + if (!MO->isReg()) { + report("generic instruction must use register operands", MI); + continue; + } - // Debug values must not have a slot index. - // Other instructions must have one, unless they are inside a bundle. - if (LiveInts) { - bool mapped = !LiveInts->isNotInMIMap(*MI); - if (MI->isDebugInstr()) { - if (mapped) - report("Debug instruction has a slot index", MI); - } else if (MI->isInsideBundle()) { - if (mapped) - report("Instruction inside bundle has a slot index", MI); + LLT OpTy = MRI->getType(MO->getReg()); + // Don't report a type mismatch if there is no actual mismatch, only a + // type missing, to reduce noise: + if (OpTy.isValid()) { + // Only the first valid type for a type index will be printed: don't + // overwrite it later so it's always clear which type was expected: + if (!Types[TypeIdx].isValid()) + Types[TypeIdx] = OpTy; + else if (Types[TypeIdx] != OpTy) + report("Type mismatch in generic instruction", MO, I, OpTy); } else { - if (!mapped) - report("Missing slot index", MI); + // Generic instructions must have types attached to their operands. + report("Generic instruction is missing a virtual register type", MO, I); } } - if (isPreISelGenericOpcode(MCID.getOpcode())) { - if (isFunctionSelected) - report("Unexpected generic instruction in a Selected function", MI); - - // Check types. - SmallVector<LLT, 4> Types; - for (unsigned I = 0; I < MCID.getNumOperands(); ++I) { - if (!MCID.OpInfo[I].isGenericType()) - continue; - // Generic instructions specify type equality constraints between some of - // their operands. Make sure these are consistent. - size_t TypeIdx = MCID.OpInfo[I].getGenericTypeIndex(); - Types.resize(std::max(TypeIdx + 1, Types.size())); - - const MachineOperand *MO = &MI->getOperand(I); - LLT OpTy = MRI->getType(MO->getReg()); - // Don't report a type mismatch if there is no actual mismatch, only a - // type missing, to reduce noise: - if (OpTy.isValid()) { - // Only the first valid type for a type index will be printed: don't - // overwrite it later so it's always clear which type was expected: - if (!Types[TypeIdx].isValid()) - Types[TypeIdx] = OpTy; - else if (Types[TypeIdx] != OpTy) - report("Type mismatch in generic instruction", MO, I, OpTy); - } else { - // Generic instructions must have types attached to their operands. - report("Generic instruction is missing a virtual register type", MO, I); - } - } - - // Generic opcodes must not have physical register operands. - for (unsigned I = 0; I < MI->getNumOperands(); ++I) { - const MachineOperand *MO = &MI->getOperand(I); - if (MO->isReg() && TargetRegisterInfo::isPhysicalRegister(MO->getReg())) - report("Generic instruction cannot have physical register", MO, I); - } + // Generic opcodes must not have physical register operands. + for (unsigned I = 0; I < MI->getNumOperands(); ++I) { + const MachineOperand *MO = &MI->getOperand(I); + if (MO->isReg() && TargetRegisterInfo::isPhysicalRegister(MO->getReg())) + report("Generic instruction cannot have physical register", MO, I); } + // Avoid out of bounds in checks below. This was already reported earlier. + if (MI->getNumOperands() < MCID.getNumOperands()) + return; + StringRef ErrorInfo; if (!TII->verifyInstruction(*MI, ErrorInfo)) report(ErrorInfo.data(), MI); // Verify properties of various specific instruction types - switch(MI->getOpcode()) { - default: + switch (MI->getOpcode()) { + case TargetOpcode::G_CONSTANT: + case TargetOpcode::G_FCONSTANT: { + if (MI->getNumOperands() < MCID.getNumOperands()) + break; + + LLT DstTy = MRI->getType(MI->getOperand(0).getReg()); + if (DstTy.isVector()) + report("Instruction cannot use a vector result type", MI); + + if (MI->getOpcode() == TargetOpcode::G_CONSTANT) { + if (!MI->getOperand(1).isCImm()) { + report("G_CONSTANT operand must be cimm", MI); + break; + } + + const ConstantInt *CI = MI->getOperand(1).getCImm(); + if (CI->getBitWidth() != DstTy.getSizeInBits()) + report("inconsistent constant size", MI); + } else { + if (!MI->getOperand(1).isFPImm()) { + report("G_FCONSTANT operand must be fpimm", MI); + break; + } + const ConstantFP *CF = MI->getOperand(1).getFPImm(); + + if (APFloat::getSizeInBits(CF->getValueAPF().getSemantics()) != + DstTy.getSizeInBits()) { + report("inconsistent constant size", MI); + } + } + break; + } case TargetOpcode::G_LOAD: case TargetOpcode::G_STORE: + case TargetOpcode::G_ZEXTLOAD: + case TargetOpcode::G_SEXTLOAD: { + LLT ValTy = MRI->getType(MI->getOperand(0).getReg()); + LLT PtrTy = MRI->getType(MI->getOperand(1).getReg()); + if (!PtrTy.isPointer()) + report("Generic memory instruction must access a pointer", MI); + // Generic loads and stores must have a single MachineMemOperand // describing that access. - if (!MI->hasOneMemOperand()) + if (!MI->hasOneMemOperand()) { report("Generic instruction accessing memory must have one mem operand", MI); + } else { + const MachineMemOperand &MMO = **MI->memoperands_begin(); + if (MI->getOpcode() == TargetOpcode::G_ZEXTLOAD || + MI->getOpcode() == TargetOpcode::G_SEXTLOAD) { + if (MMO.getSizeInBits() >= ValTy.getSizeInBits()) + report("Generic extload must have a narrower memory type", MI); + } else if (MI->getOpcode() == TargetOpcode::G_LOAD) { + if (MMO.getSize() > ValTy.getSizeInBytes()) + report("load memory size cannot exceed result size", MI); + } else if (MI->getOpcode() == TargetOpcode::G_STORE) { + if (ValTy.getSizeInBytes() < MMO.getSize()) + report("store memory size cannot exceed value size", MI); + } + } + break; + } case TargetOpcode::G_PHI: { LLT DstTy = MRI->getType(MI->getOperand(0).getReg()); if (!DstTy.isValid() || @@ -1009,6 +1052,70 @@ void MachineVerifier::visitMachineInstrBefore(const MachineInstr *MI) { MI); break; } + case TargetOpcode::G_BITCAST: { + LLT DstTy = MRI->getType(MI->getOperand(0).getReg()); + LLT SrcTy = MRI->getType(MI->getOperand(1).getReg()); + if (!DstTy.isValid() || !SrcTy.isValid()) + break; + + if (SrcTy.isPointer() != DstTy.isPointer()) + report("bitcast cannot convert between pointers and other types", MI); + + if (SrcTy.getSizeInBits() != DstTy.getSizeInBits()) + report("bitcast sizes must match", MI); + break; + } + case TargetOpcode::G_INTTOPTR: + case TargetOpcode::G_PTRTOINT: + case TargetOpcode::G_ADDRSPACE_CAST: { + LLT DstTy = MRI->getType(MI->getOperand(0).getReg()); + LLT SrcTy = MRI->getType(MI->getOperand(1).getReg()); + if (!DstTy.isValid() || !SrcTy.isValid()) + break; + + verifyVectorElementMatch(DstTy, SrcTy, MI); + + DstTy = DstTy.getScalarType(); + SrcTy = SrcTy.getScalarType(); + + if (MI->getOpcode() == TargetOpcode::G_INTTOPTR) { + if (!DstTy.isPointer()) + report("inttoptr result type must be a pointer", MI); + if (SrcTy.isPointer()) + report("inttoptr source type must not be a pointer", MI); + } else if (MI->getOpcode() == TargetOpcode::G_PTRTOINT) { + if (!SrcTy.isPointer()) + report("ptrtoint source type must be a pointer", MI); + if (DstTy.isPointer()) + report("ptrtoint result type must not be a pointer", MI); + } else { + assert(MI->getOpcode() == TargetOpcode::G_ADDRSPACE_CAST); + if (!SrcTy.isPointer() || !DstTy.isPointer()) + report("addrspacecast types must be pointers", MI); + else { + if (SrcTy.getAddressSpace() == DstTy.getAddressSpace()) + report("addrspacecast must convert different address spaces", MI); + } + } + + break; + } + case TargetOpcode::G_GEP: { + LLT DstTy = MRI->getType(MI->getOperand(0).getReg()); + LLT PtrTy = MRI->getType(MI->getOperand(1).getReg()); + LLT OffsetTy = MRI->getType(MI->getOperand(2).getReg()); + if (!DstTy.isValid() || !PtrTy.isValid() || !OffsetTy.isValid()) + break; + + if (!PtrTy.getScalarType().isPointer()) + report("gep first operand must be a pointer", MI); + + if (OffsetTy.getScalarType().isPointer()) + report("gep offset operand must not be a pointer", MI); + + // TODO: Is the offset allowed to be a scalar with a vector? + break; + } case TargetOpcode::G_SEXT: case TargetOpcode::G_ZEXT: case TargetOpcode::G_ANYEXT: @@ -1021,30 +1128,18 @@ void MachineVerifier::visitMachineInstrBefore(const MachineInstr *MI) { // instructions aren't guaranteed to have the right number of operands or // types attached to them at this point assert(MCID.getNumOperands() == 2 && "Expected 2 operands G_*{EXT,TRUNC}"); - if (MI->getNumOperands() < MCID.getNumOperands()) - break; LLT DstTy = MRI->getType(MI->getOperand(0).getReg()); LLT SrcTy = MRI->getType(MI->getOperand(1).getReg()); if (!DstTy.isValid() || !SrcTy.isValid()) break; - LLT DstElTy = DstTy.isVector() ? DstTy.getElementType() : DstTy; - LLT SrcElTy = SrcTy.isVector() ? SrcTy.getElementType() : SrcTy; + LLT DstElTy = DstTy.getScalarType(); + LLT SrcElTy = SrcTy.getScalarType(); if (DstElTy.isPointer() || SrcElTy.isPointer()) report("Generic extend/truncate can not operate on pointers", MI); - if (DstTy.isVector() != SrcTy.isVector()) { - report("Generic extend/truncate must be all-vector or all-scalar", MI); - // Generally we try to report as many issues as possible at once, but in - // this case it's not clear what should we be comparing the size of the - // scalar with: the size of the whole vector or its lane. Instead of - // making an arbitrary choice and emitting not so helpful message, let's - // avoid the extra noise and stop here. - break; - } - if (DstTy.isVector() && DstTy.getNumElements() != SrcTy.getNumElements()) - report("Generic vector extend/truncate must preserve number of lanes", - MI); + verifyVectorElementMatch(DstTy, SrcTy, MI); + unsigned DstSize = DstElTy.getSizeInBits(); unsigned SrcSize = SrcElTy.getSizeInBits(); switch (MI->getOpcode()) { @@ -1061,6 +1156,17 @@ void MachineVerifier::visitMachineInstrBefore(const MachineInstr *MI) { } break; } + case TargetOpcode::G_SELECT: { + LLT SelTy = MRI->getType(MI->getOperand(0).getReg()); + LLT CondTy = MRI->getType(MI->getOperand(1).getReg()); + if (!SelTy.isValid() || !CondTy.isValid()) + break; + + // Scalar condition select on a vector is valid. + if (CondTy.isVector()) + verifyVectorElementMatch(SelTy, CondTy, MI); + break; + } case TargetOpcode::G_MERGE_VALUES: { // G_MERGE_VALUES should only be used to merge scalars into a larger scalar, // e.g. s2N = MERGE sN, sN @@ -1070,6 +1176,16 @@ void MachineVerifier::visitMachineInstrBefore(const MachineInstr *MI) { LLT SrcTy = MRI->getType(MI->getOperand(1).getReg()); if (DstTy.isVector() || SrcTy.isVector()) report("G_MERGE_VALUES cannot operate on vectors", MI); + + const unsigned NumOps = MI->getNumOperands(); + if (DstTy.getSizeInBits() != SrcTy.getSizeInBits() * (NumOps - 1)) + report("G_MERGE_VALUES result size is inconsistent", MI); + + for (unsigned I = 2; I != NumOps; ++I) { + if (MRI->getType(MI->getOperand(I).getReg()) != SrcTy) + report("G_MERGE_VALUES source types do not match", MI); + } + break; } case TargetOpcode::G_UNMERGE_VALUES: { @@ -1092,18 +1208,23 @@ void MachineVerifier::visitMachineInstrBefore(const MachineInstr *MI) { // must match the dest vector size. LLT DstTy = MRI->getType(MI->getOperand(0).getReg()); LLT SrcEltTy = MRI->getType(MI->getOperand(1).getReg()); - if (!DstTy.isVector() || SrcEltTy.isVector()) + if (!DstTy.isVector() || SrcEltTy.isVector()) { report("G_BUILD_VECTOR must produce a vector from scalar operands", MI); + break; + } + + if (DstTy.getElementType() != SrcEltTy) + report("G_BUILD_VECTOR result element type must match source type", MI); + + if (DstTy.getNumElements() != MI->getNumOperands() - 1) + report("G_BUILD_VECTOR must have an operand for each elemement", MI); + for (unsigned i = 2; i < MI->getNumOperands(); ++i) { if (MRI->getType(MI->getOperand(1).getReg()) != MRI->getType(MI->getOperand(i).getReg())) report("G_BUILD_VECTOR source operand types are not homogeneous", MI); } - if (DstTy.getSizeInBits() != - SrcEltTy.getSizeInBits() * (MI->getNumOperands() - 1)) - report("G_BUILD_VECTOR src operands total size don't match dest " - "size.", - MI); + break; } case TargetOpcode::G_BUILD_VECTOR_TRUNC: { @@ -1144,6 +1265,176 @@ void MachineVerifier::visitMachineInstrBefore(const MachineInstr *MI) { report("G_CONCAT_VECTOR num dest and source elements should match", MI); break; } + case TargetOpcode::G_ICMP: + case TargetOpcode::G_FCMP: { + LLT DstTy = MRI->getType(MI->getOperand(0).getReg()); + LLT SrcTy = MRI->getType(MI->getOperand(2).getReg()); + + if ((DstTy.isVector() != SrcTy.isVector()) || + (DstTy.isVector() && DstTy.getNumElements() != SrcTy.getNumElements())) + report("Generic vector icmp/fcmp must preserve number of lanes", MI); + + break; + } + case TargetOpcode::G_EXTRACT: { + const MachineOperand &SrcOp = MI->getOperand(1); + if (!SrcOp.isReg()) { + report("extract source must be a register", MI); + break; + } + + const MachineOperand &OffsetOp = MI->getOperand(2); + if (!OffsetOp.isImm()) { + report("extract offset must be a constant", MI); + break; + } + + unsigned DstSize = MRI->getType(MI->getOperand(0).getReg()).getSizeInBits(); + unsigned SrcSize = MRI->getType(SrcOp.getReg()).getSizeInBits(); + if (SrcSize == DstSize) + report("extract source must be larger than result", MI); + + if (DstSize + OffsetOp.getImm() > SrcSize) + report("extract reads past end of register", MI); + break; + } + case TargetOpcode::G_INSERT: { + const MachineOperand &SrcOp = MI->getOperand(2); + if (!SrcOp.isReg()) { + report("insert source must be a register", MI); + break; + } + + const MachineOperand &OffsetOp = MI->getOperand(3); + if (!OffsetOp.isImm()) { + report("insert offset must be a constant", MI); + break; + } + + unsigned DstSize = MRI->getType(MI->getOperand(0).getReg()).getSizeInBits(); + unsigned SrcSize = MRI->getType(SrcOp.getReg()).getSizeInBits(); + + if (DstSize <= SrcSize) + report("inserted size must be smaller than total register", MI); + + if (SrcSize + OffsetOp.getImm() > DstSize) + report("insert writes past end of register", MI); + + break; + } + case TargetOpcode::G_JUMP_TABLE: { + if (!MI->getOperand(1).isJTI()) + report("G_JUMP_TABLE source operand must be a jump table index", MI); + LLT DstTy = MRI->getType(MI->getOperand(0).getReg()); + if (!DstTy.isPointer()) + report("G_JUMP_TABLE dest operand must have a pointer type", MI); + break; + } + case TargetOpcode::G_BRJT: { + if (!MRI->getType(MI->getOperand(0).getReg()).isPointer()) + report("G_BRJT src operand 0 must be a pointer type", MI); + + if (!MI->getOperand(1).isJTI()) + report("G_BRJT src operand 1 must be a jump table index", MI); + + const auto &IdxOp = MI->getOperand(2); + if (!IdxOp.isReg() || MRI->getType(IdxOp.getReg()).isPointer()) + report("G_BRJT src operand 2 must be a scalar reg type", MI); + break; + } + case TargetOpcode::G_INTRINSIC: + case TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS: { + // TODO: Should verify number of def and use operands, but the current + // interface requires passing in IR types for mangling. + const MachineOperand &IntrIDOp = MI->getOperand(MI->getNumExplicitDefs()); + if (!IntrIDOp.isIntrinsicID()) { + report("G_INTRINSIC first src operand must be an intrinsic ID", MI); + break; + } + + bool NoSideEffects = MI->getOpcode() == TargetOpcode::G_INTRINSIC; + unsigned IntrID = IntrIDOp.getIntrinsicID(); + if (IntrID != 0 && IntrID < Intrinsic::num_intrinsics) { + AttributeList Attrs + = Intrinsic::getAttributes(MF->getFunction().getContext(), + static_cast<Intrinsic::ID>(IntrID)); + bool DeclHasSideEffects = !Attrs.hasFnAttribute(Attribute::ReadNone); + if (NoSideEffects && DeclHasSideEffects) { + report("G_INTRINSIC used with intrinsic that accesses memory", MI); + break; + } + if (!NoSideEffects && !DeclHasSideEffects) { + report("G_INTRINSIC_W_SIDE_EFFECTS used with readnone intrinsic", MI); + break; + } + } + + break; + } + default: + break; + } +} + +void MachineVerifier::visitMachineInstrBefore(const MachineInstr *MI) { + const MCInstrDesc &MCID = MI->getDesc(); + if (MI->getNumOperands() < MCID.getNumOperands()) { + report("Too few operands", MI); + errs() << MCID.getNumOperands() << " operands expected, but " + << MI->getNumOperands() << " given.\n"; + } + + if (MI->isPHI()) { + if (MF->getProperties().hasProperty( + MachineFunctionProperties::Property::NoPHIs)) + report("Found PHI instruction with NoPHIs property set", MI); + + if (FirstNonPHI) + report("Found PHI instruction after non-PHI", MI); + } else if (FirstNonPHI == nullptr) + FirstNonPHI = MI; + + // Check the tied operands. + if (MI->isInlineAsm()) + verifyInlineAsm(MI); + + // Check the MachineMemOperands for basic consistency. + for (MachineInstr::mmo_iterator I = MI->memoperands_begin(), + E = MI->memoperands_end(); + I != E; ++I) { + if ((*I)->isLoad() && !MI->mayLoad()) + report("Missing mayLoad flag", MI); + if ((*I)->isStore() && !MI->mayStore()) + report("Missing mayStore flag", MI); + } + + // Debug values must not have a slot index. + // Other instructions must have one, unless they are inside a bundle. + if (LiveInts) { + bool mapped = !LiveInts->isNotInMIMap(*MI); + if (MI->isDebugInstr()) { + if (mapped) + report("Debug instruction has a slot index", MI); + } else if (MI->isInsideBundle()) { + if (mapped) + report("Instruction inside bundle has a slot index", MI); + } else { + if (!mapped) + report("Missing slot index", MI); + } + } + + if (isPreISelGenericOpcode(MCID.getOpcode())) { + verifyPreISelGenericInstruction(MI); + return; + } + + StringRef ErrorInfo; + if (!TII->verifyInstruction(*MI, ErrorInfo)) + report(ErrorInfo.data(), MI); + + // Verify properties of various specific instruction types + switch (MI->getOpcode()) { case TargetOpcode::COPY: { if (foundErrors) break; @@ -1193,7 +1484,8 @@ void MachineVerifier::visitMachineInstrBefore(const MachineInstr *MI) { VerifyStackMapConstant(VarStart + StatepointOpers::NumDeoptOperandsOffset); // TODO: verify we have properly encoded deopt arguments - }; + break; + } } void @@ -1356,7 +1648,7 @@ MachineVerifier::visitMachineOperand(const MachineOperand *MO, unsigned MONum) { return; } if (SubIdx) { - report("Generic virtual register does not subregister index", MO, + report("Generic virtual register does not allow subregister index", MO, MONum); return; } @@ -1911,6 +2203,10 @@ void MachineVerifier::visitMachineFunctionAfter() { verifyLiveVariables(); if (LiveInts) verifyLiveIntervals(); + + for (auto CSInfo : MF->getCallSitesInfo()) + if (!CSInfo.first->isCall()) + report("Call site info referencing instruction that is not call", MF); } void MachineVerifier::verifyLiveVariables() { |