make the asm matcher emitter reject instructions that have comments

in their asmstring.  Fix the two x86 "NOREX" instructions that have them.
If these comments are important, the instlowering stuff can print them.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@117897 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Chris Lattner 2010-11-01 04:44:29 +00:00
parent 5bc9387806
commit 4164f6bbbf
3 changed files with 32 additions and 41 deletions

View File

@ -98,12 +98,12 @@ def MOVZX32rm16: I<0xB7, MRMSrcMem, (outs GR32:$dst), (ins i16mem:$src),
// instead of GR32. This allows them to operate on h registers on x86-64. // instead of GR32. This allows them to operate on h registers on x86-64.
def MOVZX32_NOREXrr8 : I<0xB6, MRMSrcReg, def MOVZX32_NOREXrr8 : I<0xB6, MRMSrcReg,
(outs GR32_NOREX:$dst), (ins GR8:$src), (outs GR32_NOREX:$dst), (ins GR8:$src),
"movz{bl|x}\t{$src, $dst|$dst, $src} # NOREX", "movz{bl|x}\t{$src, $dst|$dst, $src}",
[]>, TB; []>, TB;
let mayLoad = 1 in let mayLoad = 1 in
def MOVZX32_NOREXrm8 : I<0xB6, MRMSrcMem, def MOVZX32_NOREXrm8 : I<0xB6, MRMSrcMem,
(outs GR32_NOREX:$dst), (ins i8mem:$src), (outs GR32_NOREX:$dst), (ins i8mem:$src),
"movz{bl|x}\t{$src, $dst|$dst, $src} # NOREX", "movz{bl|x}\t{$src, $dst|$dst, $src}",
[]>, TB; []>, TB;
// MOVSX64rr8 always has a REX prefix and it has an 8-bit register // MOVSX64rr8 always has a REX prefix and it has an 8-bit register

View File

@ -18,7 +18,7 @@
// CHECK: movswl 3735928559(%ebx,%ecx,8), %ecx // CHECK: movswl 3735928559(%ebx,%ecx,8), %ecx
movswl 0xdeadbeef(%ebx,%ecx,8),%ecx movswl 0xdeadbeef(%ebx,%ecx,8),%ecx
// CHECK: movzbl 3735928559(%ebx,%ecx,8), %ecx # NOREX // CHECK: movzbl 3735928559(%ebx,%ecx,8), %ecx
movzbl 0xdeadbeef(%ebx,%ecx,8),%ecx movzbl 0xdeadbeef(%ebx,%ecx,8),%ecx
// CHECK: movzwl 3735928559(%ebx,%ecx,8), %ecx // CHECK: movzwl 3735928559(%ebx,%ecx,8), %ecx
@ -11807,19 +11807,19 @@
// CHECK: movswl 305419896, %ecx // CHECK: movswl 305419896, %ecx
movswl 0x12345678,%ecx movswl 0x12345678,%ecx
// CHECK: movzbl 3735928559(%ebx,%ecx,8), %ecx # NOREX // CHECK: movzbl 3735928559(%ebx,%ecx,8), %ecx
movzbl 0xdeadbeef(%ebx,%ecx,8),%ecx movzbl 0xdeadbeef(%ebx,%ecx,8),%ecx
// CHECK: movzbl 69, %ecx # NOREX // CHECK: movzbl 69, %ecx
movzbl 0x45,%ecx movzbl 0x45,%ecx
// CHECK: movzbl 32493, %ecx # NOREX // CHECK: movzbl 32493, %ecx
movzbl 0x7eed,%ecx movzbl 0x7eed,%ecx
// CHECK: movzbl 3133065982, %ecx # NOREX // CHECK: movzbl 3133065982, %ecx
movzbl 0xbabecafe,%ecx movzbl 0xbabecafe,%ecx
// CHECK: movzbl 305419896, %ecx # NOREX // CHECK: movzbl 305419896, %ecx
movzbl 0x12345678,%ecx movzbl 0x12345678,%ecx
// CHECK: movzbw 3735928559(%ebx,%ecx,8), %bx // CHECK: movzbw 3735928559(%ebx,%ecx,8), %bx

View File

@ -355,26 +355,18 @@ struct InstructionInfo {
/// function. /// function.
std::string ConversionFnKind; std::string ConversionFnKind;
InstructionInfo(const CodeGenInstruction &CGI, StringRef CommentDelimiter) InstructionInfo(const CodeGenInstruction &CGI)
: TheDef(CGI.TheDef), OperandList(CGI.Operands) { : TheDef(CGI.TheDef), OperandList(CGI.Operands) {
InstrName = TheDef->getName(); InstrName = TheDef->getName();
// TODO: Eventually support asmparser for Variant != 0. // TODO: Eventually support asmparser for Variant != 0.
AsmString = CGI.FlattenAsmStringVariants(CGI.AsmString, 0); AsmString = CGI.FlattenAsmStringVariants(CGI.AsmString, 0);
// Remove comments from the asm string. We know that the asmstring only
// has one line.
if (!CommentDelimiter.empty()) {
size_t Idx = StringRef(AsmString).find(CommentDelimiter);
if (Idx != StringRef::npos)
AsmString = AsmString.substr(0, Idx);
}
TokenizeAsmString(AsmString, Tokens); TokenizeAsmString(AsmString, Tokens);
} }
/// isAssemblerInstruction - Return true if this matchable is a valid thing to /// isAssemblerInstruction - Return true if this matchable is a valid thing to
/// match against. /// match against.
bool isAssemblerInstruction() const; bool isAssemblerInstruction(StringRef CommentDelimiter) const;
/// getSingletonRegisterForToken - If the specified token is a singleton /// getSingletonRegisterForToken - If the specified token is a singleton
/// register, return the Record for it, otherwise return null. /// register, return the Record for it, otherwise return null.
@ -465,9 +457,6 @@ public:
/// Target - The target information. /// Target - The target information.
CodeGenTarget &Target; CodeGenTarget &Target;
/// The AsmParser "CommentDelimiter" value.
std::string CommentDelimiter;
/// The AsmParser "RegisterPrefix" value. /// The AsmParser "RegisterPrefix" value.
std::string RegisterPrefix; std::string RegisterPrefix;
@ -567,7 +556,7 @@ static Record *getRegisterRecord(CodeGenTarget &Target, StringRef Name) {
return 0; return 0;
} }
bool InstructionInfo::isAssemblerInstruction() const { bool InstructionInfo::isAssemblerInstruction(StringRef CommentDelimiter) const {
StringRef Name = InstrName; StringRef Name = InstrName;
// Reject instructions with no .s string. // Reject instructions with no .s string.
@ -581,6 +570,14 @@ bool InstructionInfo::isAssemblerInstruction() const {
"multiline instruction is not valid for the asmparser, " "multiline instruction is not valid for the asmparser, "
"mark it isCodeGenOnly"); "mark it isCodeGenOnly");
// Remove comments from the asm string. We know that the asmstring only
// has one line.
if (!CommentDelimiter.empty() &&
StringRef(AsmString).find(CommentDelimiter) != StringRef::npos)
throw TGError(TheDef->getLoc(),
"asmstring for instruction has comment character in it, "
"mark it isCodeGenOnly");
// Reject instructions with attributes, these aren't something we can handle, // Reject instructions with attributes, these aren't something we can handle,
// the target should be refactored to use operands instead of modifiers. // the target should be refactored to use operands instead of modifiers.
// //
@ -674,10 +671,8 @@ AsmMatcherInfo::getOperandClass(StringRef Token,
if (OI.Rec->isSubClassOf("RegisterClass")) { if (OI.Rec->isSubClassOf("RegisterClass")) {
ClassInfo *CI = RegisterClassClasses[OI.Rec]; ClassInfo *CI = RegisterClassClasses[OI.Rec];
if (!CI) { if (!CI)
PrintError(OI.Rec->getLoc(), "register class has no class info!"); throw TGError(OI.Rec->getLoc(), "register class has no class info!");
throw std::string("ERROR: Missing register class!");
}
return CI; return CI;
} }
@ -686,10 +681,8 @@ AsmMatcherInfo::getOperandClass(StringRef Token,
Record *MatchClass = OI.Rec->getValueAsDef("ParserMatchClass"); Record *MatchClass = OI.Rec->getValueAsDef("ParserMatchClass");
ClassInfo *CI = AsmOperandClasses[MatchClass]; ClassInfo *CI = AsmOperandClasses[MatchClass];
if (!CI) { if (!CI)
PrintError(OI.Rec->getLoc(), "operand has no match class!"); throw TGError(OI.Rec->getLoc(), "operand has no match class!");
throw std::string("ERROR: Missing match class!");
}
return CI; return CI;
} }
@ -876,7 +869,6 @@ void AsmMatcherInfo::BuildOperandClasses() {
AsmMatcherInfo::AsmMatcherInfo(Record *asmParser, CodeGenTarget &target) AsmMatcherInfo::AsmMatcherInfo(Record *asmParser, CodeGenTarget &target)
: AsmParser(asmParser), Target(target), : AsmParser(asmParser), Target(target),
CommentDelimiter(AsmParser->getValueAsString("CommentDelimiter")),
RegisterPrefix(AsmParser->getValueAsString("RegisterPrefix")) RegisterPrefix(AsmParser->getValueAsString("RegisterPrefix"))
{ {
} }
@ -891,16 +883,16 @@ void AsmMatcherInfo::BuildInfo() {
if (!Pred->getValueAsBit("AssemblerMatcherPredicate")) if (!Pred->getValueAsBit("AssemblerMatcherPredicate"))
continue; continue;
if (Pred->getName().empty()) { if (Pred->getName().empty())
PrintError(Pred->getLoc(), "Predicate has no name!"); throw TGError(Pred->getLoc(), "Predicate has no name!");
throw std::string("ERROR: Predicate defs must be named");
}
unsigned FeatureNo = SubtargetFeatures.size(); unsigned FeatureNo = SubtargetFeatures.size();
SubtargetFeatures[Pred] = new SubtargetFeatureInfo(Pred, FeatureNo); SubtargetFeatures[Pred] = new SubtargetFeatureInfo(Pred, FeatureNo);
assert(FeatureNo < 32 && "Too many subtarget features!"); assert(FeatureNo < 32 && "Too many subtarget features!");
} }
StringRef CommentDelimiter = AsmParser->getValueAsString("CommentDelimiter");
// Parse the instructions; we need to do this first so that we can gather the // Parse the instructions; we need to do this first so that we can gather the
// singleton register classes. // singleton register classes.
SmallPtrSet<Record*, 16> SingletonRegisters; SmallPtrSet<Record*, 16> SingletonRegisters;
@ -917,11 +909,11 @@ void AsmMatcherInfo::BuildInfo() {
if (CGI.TheDef->getValueAsBit("isCodeGenOnly")) if (CGI.TheDef->getValueAsBit("isCodeGenOnly"))
continue; continue;
OwningPtr<InstructionInfo> II(new InstructionInfo(CGI, CommentDelimiter)); OwningPtr<InstructionInfo> II(new InstructionInfo(CGI));
// Ignore instructions which shouldn't be matched and diagnose invalid // Ignore instructions which shouldn't be matched and diagnose invalid
// instruction definitions with an error. // instruction definitions with an error.
if (!II->isAssemblerInstruction()) if (!II->isAssemblerInstruction(CommentDelimiter))
continue; continue;
// Ignore "Int_*" and "*_Int" instructions, which are internal aliases. // Ignore "Int_*" and "*_Int" instructions, which are internal aliases.
@ -1010,8 +1002,8 @@ void AsmMatcherInfo::BuildInfo() {
// Map this token to an operand. FIXME: Move elsewhere. // Map this token to an operand. FIXME: Move elsewhere.
unsigned Idx; unsigned Idx;
if (!II->OperandList.hasOperandNamed(OperandName, Idx)) if (!II->OperandList.hasOperandNamed(OperandName, Idx))
throw std::string("error: unable to find operand: '" + throw TGError(II->TheDef->getLoc(), "error: unable to find operand: '" +
OperandName.str() + "'"); OperandName.str() + "'");
// FIXME: This is annoying, the named operand may be tied (e.g., // FIXME: This is annoying, the named operand may be tied (e.g.,
// XCHG8rm). What we want is the untied operand, which we now have to // XCHG8rm). What we want is the untied operand, which we now have to
@ -1536,8 +1528,7 @@ static bool EmitMnemonicAliases(raw_ostream &OS, const AsmMatcherInfo &Info) {
// We can't have two aliases from the same mnemonic with no predicate. // We can't have two aliases from the same mnemonic with no predicate.
PrintError(ToVec[AliasWithNoPredicate]->getLoc(), PrintError(ToVec[AliasWithNoPredicate]->getLoc(),
"two MnemonicAliases with the same 'from' mnemonic!"); "two MnemonicAliases with the same 'from' mnemonic!");
PrintError(R->getLoc(), "this is the other MnemonicAlias."); throw TGError(R->getLoc(), "this is the other MnemonicAlias.");
throw std::string("ERROR: Invalid MnemonicAlias definitions!");
} }
AliasWithNoPredicate = i; AliasWithNoPredicate = i;