-/// TokenizeAsmString - Tokenize a simplified assembly string.
-static void TokenizeAsmString(StringRef AsmString,
- SmallVectorImpl<StringRef> &Tokens) {
- unsigned Prev = 0;
- bool InTok = true;
- for (unsigned i = 0, e = AsmString.size(); i != e; ++i) {
- switch (AsmString[i]) {
- case '[':
- case ']':
- case '*':
- case '!':
- case ' ':
- case '\t':
- case ',':
- if (InTok) {
- Tokens.push_back(AsmString.slice(Prev, i));
- InTok = false;
- }
- if (!isspace(AsmString[i]) && AsmString[i] != ',')
- Tokens.push_back(AsmString.substr(i, 1));
- Prev = i + 1;
- break;
-
- case '\\':
- if (InTok) {
- Tokens.push_back(AsmString.slice(Prev, i));
- InTok = false;
- }
- ++i;
- assert(i != AsmString.size() && "Invalid quoted character");
- Tokens.push_back(AsmString.substr(i, 1));
- Prev = i + 1;
- break;
-
- case '$': {
- // If this isn't "${", treat like a normal token.
- if (i + 1 == AsmString.size() || AsmString[i + 1] != '{') {
- if (InTok) {
- Tokens.push_back(AsmString.slice(Prev, i));
- InTok = false;
- }
- Prev = i;
- break;
- }
-
- if (InTok) {
- Tokens.push_back(AsmString.slice(Prev, i));
- InTok = false;
- }
-
- StringRef::iterator End =
- std::find(AsmString.begin() + i, AsmString.end(), '}');
- assert(End != AsmString.end() && "Missing brace in operand reference!");
- size_t EndPos = End - AsmString.begin();
- Tokens.push_back(AsmString.slice(i, EndPos+1));
- Prev = EndPos + 1;
- i = EndPos;
- break;
- }
-
- case '.':
- if (InTok) {
- Tokens.push_back(AsmString.slice(Prev, i));
- }
- Prev = i;
- InTok = true;
- break;
-
- default:
- InTok = true;
- }
- }
- if (InTok && Prev != AsmString.size())
- Tokens.push_back(AsmString.substr(Prev));
-}
-
-static bool IsAssemblerInstruction(StringRef Name,
- const CodeGenInstruction &CGI,
- const SmallVectorImpl<StringRef> &Tokens) {
- // Ignore "codegen only" instructions.
- if (CGI.TheDef->getValueAsBit("isCodeGenOnly"))
- return false;
-
- // Ignore "Int_*" and "*_Int" instructions, which are internal aliases.
- //
- // FIXME: This is a total hack.
- if (StringRef(Name).startswith("Int_") || StringRef(Name).endswith("_Int"))
- return false;
-
- // Reject instructions with no .s string.
- if (CGI.AsmString.empty()) {
- PrintError(CGI.TheDef->getLoc(),
- "instruction with empty asm string");
- throw std::string("ERROR: Invalid instruction for asm matcher");
- }
-
- // Reject any instructions with a newline in them, they should be marked
- // isCodeGenOnly if they are pseudo instructions.
- if (CGI.AsmString.find('\n') != std::string::npos) {
- PrintError(CGI.TheDef->getLoc(),
- "multiline instruction is not valid for the asmparser, "
- "mark it isCodeGenOnly");
- throw std::string("ERROR: Invalid instruction");
- }
-
- // Reject instructions with attributes, these aren't something we can handle,
- // the target should be refactored to use operands instead of modifiers.
- //
- // Also, check for instructions which reference the operand multiple times;
- // this implies a constraint we would not honor.
- std::set<std::string> OperandNames;
- for (unsigned i = 1, e = Tokens.size(); i < e; ++i) {
- if (Tokens[i][0] == '$' &&
- Tokens[i].find(':') != StringRef::npos) {
- PrintError(CGI.TheDef->getLoc(),
- "instruction with operand modifier '" + Tokens[i].str() +
- "' not supported by asm matcher. Mark isCodeGenOnly!");
- throw std::string("ERROR: Invalid instruction");
- }
-
- // FIXME: Should reject these. The ARM backend hits this with $lane in a
- // bunch of instructions. It is unclear what the right answer is for this.
- if (Tokens[i][0] == '$' && !OperandNames.insert(Tokens[i]).second) {
- DEBUG({
- errs() << "warning: '" << Name << "': "
- << "ignoring instruction with tied operand '"
- << Tokens[i].str() << "'\n";
- });
- return false;
- }
- }
-
- return true;
-}
-