X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=utils%2FTableGen%2FAsmWriterEmitter.cpp;h=8fbb2cfbb61c887136cc68d75dcedf7f43f32715;hb=4c8c83022b501759d8559e224c84ae2a9921ba41;hp=d8e983940789c237222fa59d5cddd08cea8b9ad9;hpb=0a012128574c93d5b85adffd14eb4b07883fba4c;p=oota-llvm.git diff --git a/utils/TableGen/AsmWriterEmitter.cpp b/utils/TableGen/AsmWriterEmitter.cpp index d8e98394078..8fbb2cfbb61 100644 --- a/utils/TableGen/AsmWriterEmitter.cpp +++ b/utils/TableGen/AsmWriterEmitter.cpp @@ -2,8 +2,8 @@ // // The LLVM Compiler Infrastructure // -// This file was developed by the LLVM research group and is distributed under -// the University of Illinois Open Source License. See LICENSE.TXT for details. +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // @@ -19,7 +19,6 @@ #include "llvm/Support/Debug.h" #include "llvm/Support/MathExtras.h" #include -#include using namespace llvm; static bool isIdentChar(char C) { @@ -29,7 +28,8 @@ static bool isIdentChar(char C) { C == '_'; } -namespace { +// This should be an anon namespace, this works around a GCC warning. +namespace llvm { struct AsmWriterOperand { enum { isLiteralTextOperand, isMachineInstrOperand } OperandType; @@ -69,7 +69,8 @@ namespace { } namespace llvm { - struct AsmWriterInst { + class AsmWriterInst { + public: std::vector Operands; const CodeGenInstruction *CGI; @@ -98,7 +99,9 @@ std::string AsmWriterOperand::getCode() const { if (OperandType == isLiteralTextOperand) return "O << \"" + Str + "\"; "; - std::string Result = Str + "(MI, " + utostr(MIOpNo); + std::string Result = Str + "(MI"; + if (MIOpNo != ~0U) + Result += ", " + utostr(MIOpNo); if (!MiModifier.empty()) Result += ", \"" + MiModifier + '"'; return Result + "); "; @@ -119,7 +122,7 @@ AsmWriterInst::AsmWriterInst(const CodeGenInstruction &CGI, unsigned Variant) { std::string::size_type LastEmitted = 0; while (LastEmitted != AsmString.size()) { std::string::size_type DollarPos = - AsmString.find_first_of("${|}", LastEmitted); + AsmString.find_first_of("${|}\\", LastEmitted); if (DollarPos == std::string::npos) DollarPos = AsmString.size(); // Emit a constant string fragment. @@ -129,6 +132,23 @@ AsmWriterInst::AsmWriterInst(const CodeGenInstruction &CGI, unsigned Variant) { AddLiteralString(std::string(AsmString.begin()+LastEmitted, AsmString.begin()+DollarPos)); LastEmitted = DollarPos; + } else if (AsmString[DollarPos] == '\\') { + if (DollarPos+1 != AsmString.size() && + (CurVariant == Variant || CurVariant == ~0U)) { + if (AsmString[DollarPos+1] == 'n') { + AddLiteralString("\\n"); + } else if (AsmString[DollarPos+1] == 't') { + AddLiteralString("\\t"); + } else if (std::string("${|}\\").find(AsmString[DollarPos+1]) + != std::string::npos) { + AddLiteralString(std::string(1, AsmString[DollarPos+1])); + } else { + throw "Non-supported escaped character found in instruction '" + + CGI.TheDef->getName() + "'!"; + } + LastEmitted = DollarPos+2; + continue; + } } else if (AsmString[DollarPos] == '{') { if (CurVariant != ~0U) throw "Nested variants found for instruction '" + @@ -172,7 +192,8 @@ AsmWriterInst::AsmWriterInst(const CodeGenInstruction &CGI, unsigned Variant) { AsmString.begin()+VarEnd); // Modifier - Support ${foo:modifier} syntax, where "modifier" is passed - // into printOperand. + // into printOperand. Also support ${:feature}, which is passed into + // PrintSpecial. std::string Modifier; // In order to avoid starting the next string at the terminating curly @@ -204,26 +225,24 @@ AsmWriterInst::AsmWriterInst(const CodeGenInstruction &CGI, unsigned Variant) { + CGI.TheDef->getName() + "'"; ++VarEnd; } - if (VarName.empty()) + if (VarName.empty() && Modifier.empty()) throw "Stray '$' in '" + CGI.TheDef->getName() + "' asm string, maybe you want $$?"; - unsigned OpNo = CGI.getOperandNamed(VarName); - CodeGenInstruction::OperandInfo OpInfo = CGI.OperandList[OpNo]; - - // If this is a two-address instruction and we are not accessing the - // 0th operand, remove an operand. - unsigned MIOp = OpInfo.MIOperandNo; - if (CGI.isTwoAddress && MIOp != 0) { - if (MIOp == 1) - throw "Should refer to operand #0 instead of #1 for two-address" - " instruction '" + CGI.TheDef->getName() + "'!"; - --MIOp; + if (VarName.empty()) { + // Just a modifier, pass this into PrintSpecial. + Operands.push_back(AsmWriterOperand("PrintSpecial", ~0U, Modifier)); + } else { + // Otherwise, normal operand. + unsigned OpNo = CGI.getOperandNamed(VarName); + CodeGenInstruction::OperandInfo OpInfo = CGI.OperandList[OpNo]; + + if (CurVariant == Variant || CurVariant == ~0U) { + unsigned MIOp = OpInfo.MIOperandNo; + Operands.push_back(AsmWriterOperand(OpInfo.PrinterMethodName, MIOp, + Modifier)); + } } - - if (CurVariant == Variant || CurVariant == ~0U) - Operands.push_back(AsmWriterOperand(OpInfo.PrinterMethodName, MIOp, - Modifier)); LastEmitted = VarEnd; } } @@ -240,11 +259,12 @@ unsigned AsmWriterInst::MatchesAllButOneOp(const AsmWriterInst &Other)const{ unsigned MismatchOperand = ~0U; for (unsigned i = 0, e = Operands.size(); i != e; ++i) { - if (Operands[i] != Other.Operands[i]) + if (Operands[i] != Other.Operands[i]) { if (MismatchOperand != ~0U) // Already have one mismatch? return ~1U; else MismatchOperand = i; + } } return MismatchOperand; } @@ -332,7 +352,7 @@ void AsmWriterEmitter:: FindUniqueOperandCommands(std::vector &UniqueOperandCommands, std::vector &InstIdxs, std::vector &InstOpsUsed) const { - InstIdxs.assign(NumberedInstructions.size(), 0); + InstIdxs.assign(NumberedInstructions.size(), ~0U); // This vector parallels UniqueOperandCommands, keeping track of which // instructions each case are used for. It is a comma separated string of @@ -343,7 +363,7 @@ FindUniqueOperandCommands(std::vector &UniqueOperandCommands, for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) { const AsmWriterInst *Inst = getAsmWriterInstByID(i); - if (Inst == 0) continue; // PHI, INLINEASM, etc. + if (Inst == 0) continue; // PHI, INLINEASM, LABEL, etc. std::string Command; if (Inst->Operands.empty()) @@ -478,9 +498,10 @@ void AsmWriterEmitter::run(std::ostream &O) { // Build an aggregate string, and build a table of offsets into it. std::map StringOffset; std::string AggregateString; - AggregateString += '\0'; + AggregateString.push_back(0); // "\0" + AggregateString.push_back(0); // "\0" - /// OpcodeInfo - Theis encodes the index of the string to use for the first + /// OpcodeInfo - This encodes the index of the string to use for the first /// chunk of the output as well as indices used for operand printing. std::vector OpcodeInfo; @@ -488,9 +509,14 @@ void AsmWriterEmitter::run(std::ostream &O) { for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) { AsmWriterInst *AWI = CGIAWIMap[NumberedInstructions[i]]; unsigned Idx; - if (AWI == 0 || AWI->Operands[0].Str.empty()) { + if (AWI == 0) { // Something not handled by the asmwriter printer. Idx = 0; + } else if (AWI->Operands[0].OperandType != + AsmWriterOperand::isLiteralTextOperand || + AWI->Operands[0].Str.empty()) { + // Something handled by the asmwriter printer, but with no leading string. + Idx = 1; } else { unsigned &Entry = StringOffset[AWI->Operands[0].Str]; if (Entry == 0) { @@ -510,7 +536,7 @@ void AsmWriterEmitter::run(std::ostream &O) { } // Figure out how many bits we used for the string index. - unsigned AsmStrBits = Log2_32_Ceil(MaxStringIdx); + unsigned AsmStrBits = Log2_32_Ceil(MaxStringIdx+1); // To reduce code size, we compactify common instructions into a few bits // in the opcode-indexed table. @@ -522,10 +548,10 @@ void AsmWriterEmitter::run(std::ostream &O) { while (1) { std::vector UniqueOperandCommands; - // For the first operand check, add a default value that unhandled - // instructions will use. + // For the first operand check, add a default value for instructions with + // just opcode strings to use. if (isFirst) { - UniqueOperandCommands.push_back(" return false;\n"); + UniqueOperandCommands.push_back(" return true;\n"); isFirst = false; } @@ -543,15 +569,16 @@ void AsmWriterEmitter::run(std::ostream &O) { // If we don't have enough bits for this operand, don't include it. if (NumBits > BitsLeft) { - DEBUG(std::cerr << "Not enough bits to densely encode " << NumBits - << " more bits\n"); + DOUT << "Not enough bits to densely encode " << NumBits + << " more bits\n"; break; } // Otherwise, we can include this in the initial lookup table. Add it in. BitsLeft -= NumBits; for (unsigned i = 0, e = InstIdxs.size(); i != e; ++i) - OpcodeInfo[i] |= InstIdxs[i] << (BitsLeft+AsmStrBits); + if (InstIdxs[i] != ~0U) + OpcodeInfo[i] |= InstIdxs[i] << (BitsLeft+AsmStrBits); // Remove the info about this operand. for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) { @@ -611,12 +638,25 @@ void AsmWriterEmitter::run(std::ostream &O) { O << "\";\n\n"; O << " if (MI->getOpcode() == TargetInstrInfo::INLINEASM) {\n" + << " O << \"\\t\";\n" << " printInlineAsm(MI);\n" << " return true;\n" + << " } else if (MI->getOpcode() == TargetInstrInfo::LABEL) {\n" + << " printLabel(MI);\n" + << " return true;\n" + << " } else if (MI->getOpcode() == TargetInstrInfo::DECLARE) {\n" + << " printDeclare(MI);\n" + << " return true;\n" + << " } else if (MI->getOpcode() == TargetInstrInfo::IMPLICIT_DEF) {\n" + << " printImplicitDef(MI);\n" + << " return true;\n" << " }\n\n"; + O << " O << \"\\t\";\n\n"; + O << " // Emit the opcode for the instruction.\n" << " unsigned Bits = OpInfo[MI->getOpcode()];\n" + << " if (Bits == 0) return false;\n" << " O << AsmStrs+(Bits & " << (1 << AsmStrBits)-1 << ");\n\n"; // Output the table driven operand information.