-/// FlattenVariants - Flatten an .td file assembly string by selecting the
-/// variant at index \arg N.
-static std::string FlattenVariants(const std::string &AsmString,
- unsigned N) {
- StringRef Cur = AsmString;
- std::string Res = "";
-
- for (;;) {
- // Find the start of the next variant string.
- size_t VariantsStart = 0;
- for (size_t e = Cur.size(); VariantsStart != e; ++VariantsStart)
- if (Cur[VariantsStart] == '{' &&
- (VariantsStart == 0 || (Cur[VariantsStart-1] != '$' &&
- Cur[VariantsStart-1] != '\\')))
- break;
-
- // Add the prefix to the result.
- Res += Cur.slice(0, VariantsStart);
- if (VariantsStart == Cur.size())
- break;
-
- ++VariantsStart; // Skip the '{'.
-
- // Scan to the end of the variants string.
- size_t VariantsEnd = VariantsStart;
- unsigned NestedBraces = 1;
- for (size_t e = Cur.size(); VariantsEnd != e; ++VariantsEnd) {
- if (Cur[VariantsEnd] == '}' && Cur[VariantsEnd-1] != '\\') {
- if (--NestedBraces == 0)
- break;
- } else if (Cur[VariantsEnd] == '{')
- ++NestedBraces;
- }
-
- // Select the Nth variant (or empty).
- StringRef Selection = Cur.slice(VariantsStart, VariantsEnd);
- for (unsigned i = 0; i != N; ++i)
- Selection = Selection.split('|').second;
- Res += Selection.split('|').first;
-
- assert(VariantsEnd != Cur.size() &&
- "Unterminated variants in assembly string!");
- Cur = Cur.substr(VariantsEnd + 1);
- }
-
- return Res;
-}
-
-/// 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 pseudo ops.
- //
- // FIXME: This is a hack; can we convert these instructions to set the
- // "codegen only" bit instead?
- if (const RecordVal *Form = CGI.TheDef->getValue("Form"))
- if (Form->getValue()->getAsString() == "Pseudo")
- 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;
-
- // Ignore instructions with no .s string.
- //
- // FIXME: What are these?
- if (CGI.AsmString.empty())
- return false;
-
- // FIXME: Hack; ignore any instructions with a newline in them.
- if (std::find(CGI.AsmString.begin(),
- CGI.AsmString.end(), '\n') != CGI.AsmString.end())
- return false;
-
- // Ignore instructions with attributes, these are always fake instructions for
- // simplifying codegen.
- //
- // FIXME: Is this true?
- //
- // 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] == '$' &&
- std::find(Tokens[i].begin(),
- Tokens[i].end(), ':') != Tokens[i].end()) {
- DEBUG({
- errs() << "warning: '" << Name << "': "
- << "ignoring instruction; operand with attribute '"
- << Tokens[i] << "'\n";
- });
- return false;
- }
-
- 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;
-}
-