Index: lib/CodeGen/MachineVerifier.cpp =================================================================== --- lib/CodeGen/MachineVerifier.cpp +++ lib/CodeGen/MachineVerifier.cpp @@ -230,6 +230,8 @@ void visitMachineFunctionBefore(); void visitMachineBasicBlockBefore(const MachineBasicBlock *MBB); void visitMachineBundleBefore(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); @@ -888,108 +890,58 @@ } } -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; +void MachineVerifier::verifyPreISelGenericInstruction(const MachineInstr *MI) { + if (isFunctionSelected) + report("Unexpected generic instruction in a Selected function", MI); - // Check the tied operands. - if (MI->isInlineAsm()) - verifyInlineAsm(MI); + const MCInstrDesc &MCID = MI->getDesc(); + unsigned NumOps = MI->getNumOperands(); - // Check the MachineMemOperands for basic consistency. - for (MachineInstr::mmo_iterator I = MI->memoperands_begin(), - E = MI->memoperands_end(); + // Check types. + SmallVector 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); - } - - // 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); + 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 { - 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); - - unsigned NumOps = MI->getNumOperands(); - - // Check types. - SmallVector Types; - for (unsigned I = 0, E = std::min(MCID.getNumOperands(), NumOps); - I != E; ++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); - } - - // Avoid out of bounds in checks below. This was already reported earlier. - if (MI->getNumOperands() < MCID.getNumOperands()) - return; + // 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: - break; + switch (MI->getOpcode()) { case TargetOpcode::G_CONSTANT: case TargetOpcode::G_FCONSTANT: { if (MI->getNumOperands() < MCID.getNumOperands()) @@ -1254,36 +1206,6 @@ report("G_CONCAT_VECTOR num dest and source elements should match", MI); break; } - case TargetOpcode::COPY: { - if (foundErrors) - break; - const MachineOperand &DstOp = MI->getOperand(0); - const MachineOperand &SrcOp = MI->getOperand(1); - LLT DstTy = MRI->getType(DstOp.getReg()); - LLT SrcTy = MRI->getType(SrcOp.getReg()); - if (SrcTy.isValid() && DstTy.isValid()) { - // If both types are valid, check that the types are the same. - if (SrcTy != DstTy) { - report("Copy Instruction is illegal with mismatching types", MI); - errs() << "Def = " << DstTy << ", Src = " << SrcTy << "\n"; - } - } - if (SrcTy.isValid() || DstTy.isValid()) { - // If one of them have valid types, let's just check they have the same - // size. - unsigned SrcSize = TRI->getRegSizeInBits(SrcOp.getReg(), *MRI); - unsigned DstSize = TRI->getRegSizeInBits(DstOp.getReg(), *MRI); - assert(SrcSize && "Expecting size here"); - assert(DstSize && "Expecting size here"); - if (SrcSize != DstSize) - if (!DstOp.getSubReg() && !SrcOp.getSubReg()) { - report("Copy Instruction is illegal with mismatching sizes", MI); - errs() << "Def Size = " << DstSize << ", Src Size = " << SrcSize - << "\n"; - } - } - break; - } case TargetOpcode::G_ICMP: case TargetOpcode::G_FCMP: { LLT DstTy = MRI->getType(MI->getOperand(0).getReg()); @@ -1295,26 +1217,120 @@ break; } - case TargetOpcode::STATEPOINT: - if (!MI->getOperand(StatepointOpers::IDPos).isImm() || - !MI->getOperand(StatepointOpers::NBytesPos).isImm() || - !MI->getOperand(StatepointOpers::NCallArgsPos).isImm()) - report("meta operands to STATEPOINT not constant!", MI); + default: break; + } +} - auto VerifyStackMapConstant = [&](unsigned Offset) { - if (!MI->getOperand(Offset).isImm() || - MI->getOperand(Offset).getImm() != StackMaps::ConstantOp || - !MI->getOperand(Offset + 1).isImm()) - report("stack map constant to STATEPOINT not well formed!", MI); - }; - const unsigned VarStart = StatepointOpers(MI).getVarIdx(); - VerifyStackMapConstant(VarStart + StatepointOpers::CCOffset); - VerifyStackMapConstant(VarStart + StatepointOpers::FlagsOffset); - VerifyStackMapConstant(VarStart + StatepointOpers::NumDeoptOperandsOffset); +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"; + } - // TODO: verify we have properly encoded deopt arguments - }; + 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); + } else { + 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; + const MachineOperand &DstOp = MI->getOperand(0); + const MachineOperand &SrcOp = MI->getOperand(1); + LLT DstTy = MRI->getType(DstOp.getReg()); + LLT SrcTy = MRI->getType(SrcOp.getReg()); + if (SrcTy.isValid() && DstTy.isValid()) { + // If both types are valid, check that the types are the same. + if (SrcTy != DstTy) { + report("Copy Instruction is illegal with mismatching types", MI); + errs() << "Def = " << DstTy << ", Src = " << SrcTy << "\n"; + } + } + if (SrcTy.isValid() || DstTy.isValid()) { + // If one of them have valid types, let's just check they have the same + // size. + unsigned SrcSize = TRI->getRegSizeInBits(SrcOp.getReg(), *MRI); + unsigned DstSize = TRI->getRegSizeInBits(DstOp.getReg(), *MRI); + assert(SrcSize && "Expecting size here"); + assert(DstSize && "Expecting size here"); + if (SrcSize != DstSize) + if (!DstOp.getSubReg() && !SrcOp.getSubReg()) { + report("Copy Instruction is illegal with mismatching sizes", MI); + errs() << "Def Size = " << DstSize << ", Src Size = " << SrcSize + << "\n"; + } + } + break; + } + case TargetOpcode::STATEPOINT: + if (!MI->getOperand(StatepointOpers::IDPos).isImm() || + !MI->getOperand(StatepointOpers::NBytesPos).isImm() || + !MI->getOperand(StatepointOpers::NCallArgsPos).isImm()) + report("meta operands to STATEPOINT not constant!", MI); + break; + + auto VerifyStackMapConstant = [&](unsigned Offset) { + if (!MI->getOperand(Offset).isImm() || + MI->getOperand(Offset).getImm() != StackMaps::ConstantOp || + !MI->getOperand(Offset + 1).isImm()) + report("stack map constant to STATEPOINT not well formed!", MI); + }; + const unsigned VarStart = StatepointOpers(MI).getVarIdx(); + VerifyStackMapConstant(VarStart + StatepointOpers::CCOffset); + VerifyStackMapConstant(VarStart + StatepointOpers::FlagsOffset); + VerifyStackMapConstant(VarStart + StatepointOpers::NumDeoptOperandsOffset); + + // TODO: verify we have properly encoded deopt arguments + break; + } + } } void