mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-23 11:13:28 +01:00
ARM: improved assembler diagnostics for missing CPU features.
When an instruction match is found, but the subtarget features it requires are not available (missing floating point unit, or thumb vs arm mode, for example), issue a diagnostic that identifies what the feature mismatch is. rdar://11257547 llvm-svn: 155499
This commit is contained in:
parent
47f01c373e
commit
7ac2ac85a8
@ -438,6 +438,10 @@ class Predicate<string cond> {
|
||||
/// e.g. "ModeThumb,FeatureThumb2" is translated to
|
||||
/// "(Bits & ModeThumb) != 0 && (Bits & FeatureThumb2) != 0".
|
||||
string AssemblerCondString = "";
|
||||
|
||||
/// PredicateName - User-level name to use for the predicate. Mainly for use
|
||||
/// in diagnostics such as missing feature errors in the asm matcher.
|
||||
string PredicateName = "";
|
||||
}
|
||||
|
||||
/// NoHonorSignDependentRounding - This predicate is true if support for
|
||||
@ -761,9 +765,10 @@ def DefaultAsmParserVariant : AsmParserVariant;
|
||||
|
||||
/// AssemblerPredicate - This is a Predicate that can be used when the assembler
|
||||
/// matches instructions and aliases.
|
||||
class AssemblerPredicate<string cond> {
|
||||
class AssemblerPredicate<string cond, string name = ""> {
|
||||
bit AssemblerMatcherPredicate = 1;
|
||||
string AssemblerCondString = cond;
|
||||
string PredicateName = name;
|
||||
}
|
||||
|
||||
/// TokenAlias - This class allows targets to define assembler token
|
||||
|
@ -161,53 +161,59 @@ def ARMbfi : SDNode<"ARMISD::BFI", SDT_ARMBFI>;
|
||||
// ARM Instruction Predicate Definitions.
|
||||
//
|
||||
def HasV4T : Predicate<"Subtarget->hasV4TOps()">,
|
||||
AssemblerPredicate<"HasV4TOps">;
|
||||
AssemblerPredicate<"HasV4TOps", "armv4t">;
|
||||
def NoV4T : Predicate<"!Subtarget->hasV4TOps()">;
|
||||
def HasV5T : Predicate<"Subtarget->hasV5TOps()">;
|
||||
def HasV5TE : Predicate<"Subtarget->hasV5TEOps()">,
|
||||
AssemblerPredicate<"HasV5TEOps">;
|
||||
AssemblerPredicate<"HasV5TEOps", "armv5te">;
|
||||
def HasV6 : Predicate<"Subtarget->hasV6Ops()">,
|
||||
AssemblerPredicate<"HasV6Ops">;
|
||||
AssemblerPredicate<"HasV6Ops", "armv6">;
|
||||
def NoV6 : Predicate<"!Subtarget->hasV6Ops()">;
|
||||
def HasV6T2 : Predicate<"Subtarget->hasV6T2Ops()">,
|
||||
AssemblerPredicate<"HasV6T2Ops">;
|
||||
AssemblerPredicate<"HasV6T2Ops", "armv6t2">;
|
||||
def NoV6T2 : Predicate<"!Subtarget->hasV6T2Ops()">;
|
||||
def HasV7 : Predicate<"Subtarget->hasV7Ops()">,
|
||||
AssemblerPredicate<"HasV7Ops">;
|
||||
AssemblerPredicate<"HasV7Ops", "armv7">;
|
||||
def NoVFP : Predicate<"!Subtarget->hasVFP2()">;
|
||||
def HasVFP2 : Predicate<"Subtarget->hasVFP2()">,
|
||||
AssemblerPredicate<"FeatureVFP2">;
|
||||
AssemblerPredicate<"FeatureVFP2", "VFP2">;
|
||||
def HasVFP3 : Predicate<"Subtarget->hasVFP3()">,
|
||||
AssemblerPredicate<"FeatureVFP3">;
|
||||
AssemblerPredicate<"FeatureVFP3", "VFP3">;
|
||||
def HasVFP4 : Predicate<"Subtarget->hasVFP4()">,
|
||||
AssemblerPredicate<"FeatureVFP4">;
|
||||
AssemblerPredicate<"FeatureVFP4", "VFP4">;
|
||||
def HasNEON : Predicate<"Subtarget->hasNEON()">,
|
||||
AssemblerPredicate<"FeatureNEON">;
|
||||
AssemblerPredicate<"FeatureNEON", "NEON">;
|
||||
def HasFP16 : Predicate<"Subtarget->hasFP16()">,
|
||||
AssemblerPredicate<"FeatureFP16">;
|
||||
AssemblerPredicate<"FeatureFP16","half-float">;
|
||||
def HasDivide : Predicate<"Subtarget->hasDivide()">,
|
||||
AssemblerPredicate<"FeatureHWDiv">;
|
||||
AssemblerPredicate<"FeatureHWDiv", "divide">;
|
||||
def HasT2ExtractPack : Predicate<"Subtarget->hasT2ExtractPack()">,
|
||||
AssemblerPredicate<"FeatureT2XtPk">;
|
||||
AssemblerPredicate<"FeatureT2XtPk",
|
||||
"pack/extract">;
|
||||
def HasThumb2DSP : Predicate<"Subtarget->hasThumb2DSP()">,
|
||||
AssemblerPredicate<"FeatureDSPThumb2">;
|
||||
AssemblerPredicate<"FeatureDSPThumb2",
|
||||
"thumb2-dsp">;
|
||||
def HasDB : Predicate<"Subtarget->hasDataBarrier()">,
|
||||
AssemblerPredicate<"FeatureDB">;
|
||||
AssemblerPredicate<"FeatureDB",
|
||||
"data-barriers">;
|
||||
def HasMP : Predicate<"Subtarget->hasMPExtension()">,
|
||||
AssemblerPredicate<"FeatureMP">;
|
||||
AssemblerPredicate<"FeatureMP",
|
||||
"mp-extensions">;
|
||||
def UseNEONForFP : Predicate<"Subtarget->useNEONForSinglePrecisionFP()">;
|
||||
def DontUseNEONForFP : Predicate<"!Subtarget->useNEONForSinglePrecisionFP()">;
|
||||
def IsThumb : Predicate<"Subtarget->isThumb()">,
|
||||
AssemblerPredicate<"ModeThumb">;
|
||||
AssemblerPredicate<"ModeThumb", "thumb">;
|
||||
def IsThumb1Only : Predicate<"Subtarget->isThumb1Only()">;
|
||||
def IsThumb2 : Predicate<"Subtarget->isThumb2()">,
|
||||
AssemblerPredicate<"ModeThumb,FeatureThumb2">;
|
||||
AssemblerPredicate<"ModeThumb,FeatureThumb2",
|
||||
"thumb2">;
|
||||
def IsMClass : Predicate<"Subtarget->isMClass()">,
|
||||
AssemblerPredicate<"FeatureMClass">;
|
||||
AssemblerPredicate<"FeatureMClass", "armv7m">;
|
||||
def IsARClass : Predicate<"!Subtarget->isMClass()">,
|
||||
AssemblerPredicate<"!FeatureMClass">;
|
||||
AssemblerPredicate<"!FeatureMClass",
|
||||
"armv7a/r">;
|
||||
def IsARM : Predicate<"!Subtarget->isThumb()">,
|
||||
AssemblerPredicate<"!ModeThumb">;
|
||||
AssemblerPredicate<"!ModeThumb", "arm-mode">;
|
||||
def IsIOS : Predicate<"Subtarget->isTargetIOS()">;
|
||||
def IsNotIOS : Predicate<"!Subtarget->isTargetIOS()">;
|
||||
def IsNaCl : Predicate<"Subtarget->isTargetNaCl()">;
|
||||
|
@ -7277,6 +7277,7 @@ unsigned ARMAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
|
||||
return Match_Success;
|
||||
}
|
||||
|
||||
static const char *getSubtargetFeatureName(unsigned Val);
|
||||
bool ARMAsmParser::
|
||||
MatchAndEmitInstruction(SMLoc IDLoc,
|
||||
SmallVectorImpl<MCParsedAsmOperand*> &Operands,
|
||||
@ -7317,9 +7318,21 @@ MatchAndEmitInstruction(SMLoc IDLoc,
|
||||
Inst.setLoc(IDLoc);
|
||||
Out.EmitInstruction(Inst);
|
||||
return false;
|
||||
case Match_MissingFeature:
|
||||
Error(IDLoc, "instruction requires a CPU feature not currently enabled");
|
||||
return true;
|
||||
case Match_MissingFeature: {
|
||||
assert(ErrorInfo && "Unknown missing feature!");
|
||||
// Special case the error message for the very common case where only
|
||||
// a single subtarget feature is missing (Thumb vs. ARM, e.g.).
|
||||
std::string Msg = "instruction requires:";
|
||||
unsigned Mask = 1;
|
||||
for (unsigned i = 0; i < (sizeof(ErrorInfo)*8-1); ++i) {
|
||||
if (ErrorInfo & Mask) {
|
||||
Msg += " ";
|
||||
Msg += getSubtargetFeatureName(ErrorInfo & Mask);
|
||||
}
|
||||
Mask <<= 1;
|
||||
}
|
||||
return Error(IDLoc, Msg);
|
||||
}
|
||||
case Match_InvalidOperand: {
|
||||
SMLoc ErrorLoc = IDLoc;
|
||||
if (ErrorInfo != ~0U) {
|
||||
|
@ -67,7 +67,7 @@ error: invalid operand for instruction
|
||||
@ Invalid writeback and register lists for STM
|
||||
stm r1, {r2, r6}
|
||||
stm r1!, {r2, r9}
|
||||
@ CHECK-ERRORS: error: instruction requires a CPU feature not currently enabled
|
||||
@ CHECK-ERRORS: error: instruction requires: thumb2
|
||||
@ CHECK-ERRORS: stm r1, {r2, r6}
|
||||
@ CHECK-ERRORS: ^
|
||||
@ CHECK-ERRORS: error: registers must be in range r0-r7
|
||||
@ -95,13 +95,13 @@ error: invalid operand for instruction
|
||||
str r2, [r7, #-1]
|
||||
str r5, [r1, #3]
|
||||
str r3, [r7, #128]
|
||||
@ CHECK-ERRORS: error: instruction requires a CPU feature not currently enabled
|
||||
@ CHECK-ERRORS: error: instruction requires: thumb2
|
||||
@ CHECK-ERRORS: str r2, [r7, #-1]
|
||||
@ CHECK-ERRORS: ^
|
||||
@ CHECK-ERRORS: error: instruction requires a CPU feature not currently enabled
|
||||
@ CHECK-ERRORS: error: instruction requires: thumb2
|
||||
@ CHECK-ERRORS: str r5, [r1, #3]
|
||||
@ CHECK-ERRORS: ^
|
||||
@ CHECK-ERRORS: error: instruction requires a CPU feature not currently enabled
|
||||
@ CHECK-ERRORS: error: instruction requires: thumb2
|
||||
@ CHECK-ERRORS: str r3, [r7, #128]
|
||||
@ CHECK-ERRORS: ^
|
||||
|
||||
@ -111,7 +111,7 @@ error: invalid operand for instruction
|
||||
@ CHECK-ERRORS: error: invalid operand for instruction
|
||||
@ CHECK-ERRORS: svc #-1
|
||||
@ CHECK-ERRORS: ^
|
||||
@ CHECK-ERRORS: error: instruction requires a CPU feature not currently enabled
|
||||
@ CHECK-ERRORS: error: instruction requires: arm-mode
|
||||
@ CHECK-ERRORS: svc #256
|
||||
@ CHECK-ERRORS: ^
|
||||
|
||||
@ -121,15 +121,15 @@ error: invalid operand for instruction
|
||||
add sp, #3
|
||||
add sp, sp, #512
|
||||
add r2, sp, #1024
|
||||
@ CHECK-ERRORS: error: instruction requires a CPU feature not currently enabled
|
||||
@ CHECK-ERRORS: error: instruction requires: thumb2
|
||||
@ CHECK-ERRORS: add sp, #-1
|
||||
@ CHECK-ERRORS: ^
|
||||
@ CHECK-ERRORS: error: instruction requires a CPU feature not currently enabled
|
||||
@ CHECK-ERRORS: error: instruction requires: thumb2
|
||||
@ CHECK-ERRORS: add sp, #3
|
||||
@ CHECK-ERRORS: ^
|
||||
@ CHECK-ERRORS: error: instruction requires a CPU feature not currently enabled
|
||||
@ CHECK-ERRORS: error: instruction requires: thumb2
|
||||
@ CHECK-ERRORS: add sp, sp, #512
|
||||
@ CHECK-ERRORS: ^
|
||||
@ CHECK-ERRORS: error: instruction requires a CPU feature not currently enabled
|
||||
@ CHECK-ERRORS: error: instruction requires: arm-mode
|
||||
@ CHECK-ERRORS: add r2, sp, #1024
|
||||
@ CHECK-ERRORS: ^
|
||||
|
@ -1951,6 +1951,25 @@ static void emitSubtargetFeatureFlagEnumeration(AsmMatcherInfo &Info,
|
||||
OS << "};\n\n";
|
||||
}
|
||||
|
||||
/// emitGetSubtargetFeatureName - Emit the helper function to get the
|
||||
/// user-level name for a subtarget feature.
|
||||
static void emitGetSubtargetFeatureName(AsmMatcherInfo &Info, raw_ostream &OS) {
|
||||
OS << "// User-level names for subtarget features that participate in\n"
|
||||
<< "// instruction matching.\n"
|
||||
<< "static const char *getSubtargetFeatureName(unsigned Val) {\n"
|
||||
<< " switch(Val) {\n";
|
||||
for (std::map<Record*, SubtargetFeatureInfo*>::const_iterator
|
||||
it = Info.SubtargetFeatures.begin(),
|
||||
ie = Info.SubtargetFeatures.end(); it != ie; ++it) {
|
||||
SubtargetFeatureInfo &SFI = *it->second;
|
||||
// FIXME: Totally just a placeholder name to get the algorithm working.
|
||||
OS << " case " << SFI.getEnumName() << ": return \""
|
||||
<< SFI.TheDef->getValueAsString("PredicateName") << "\";\n";
|
||||
}
|
||||
OS << " default: return \"(unknown)\";\n";
|
||||
OS << " }\n}\n\n";
|
||||
}
|
||||
|
||||
/// emitComputeAvailableFeatures - Emit the function to compute the list of
|
||||
/// available features given a subtarget.
|
||||
static void emitComputeAvailableFeatures(AsmMatcherInfo &Info,
|
||||
@ -2380,6 +2399,9 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
|
||||
OS << "\n#ifdef GET_MATCHER_IMPLEMENTATION\n";
|
||||
OS << "#undef GET_MATCHER_IMPLEMENTATION\n\n";
|
||||
|
||||
// Generate the helper function to get the names for subtarget features.
|
||||
emitGetSubtargetFeatureName(Info, OS);
|
||||
|
||||
// Generate the function that remaps for mnemonic aliases.
|
||||
bool HasMnemonicAliases = emitMnemonicAliases(OS, Info);
|
||||
|
||||
@ -2510,8 +2532,8 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
|
||||
<< Target.getName() << ClassName << "::\n"
|
||||
<< "MatchInstructionImpl(const SmallVectorImpl<MCParsedAsmOperand*>"
|
||||
<< " &Operands,\n";
|
||||
OS << " MCInst &Inst, unsigned &ErrorInfo,\n";
|
||||
OS << " unsigned VariantID) {\n";
|
||||
OS << " MCInst &Inst, unsigned &ErrorInfo, ";
|
||||
OS << "unsigned VariantID) {\n";
|
||||
|
||||
// Emit code to get the available features.
|
||||
OS << " // Get the current feature set.\n";
|
||||
@ -2586,6 +2608,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
|
||||
OS << " if ((AvailableFeatures & it->RequiredFeatures) "
|
||||
<< "!= it->RequiredFeatures) {\n";
|
||||
OS << " HadMatchOtherThanFeatures = true;\n";
|
||||
OS << " ErrorInfo = it->RequiredFeatures & ~AvailableFeatures;\n";
|
||||
OS << " continue;\n";
|
||||
OS << " }\n";
|
||||
OS << "\n";
|
||||
@ -2620,6 +2643,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
|
||||
OS << " // Okay, we had no match. Try to return a useful error code.\n";
|
||||
OS << " if (HadMatchOtherThanPredicate || !HadMatchOtherThanFeatures)";
|
||||
OS << " return RetCode;\n";
|
||||
OS << " assert(ErrorInfo && \"missing feature(s) but what?!\");";
|
||||
OS << " return Match_MissingFeature;\n";
|
||||
OS << "}\n\n";
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user