[llvm-commits] CVS: llvm/lib/CodeGen/AsmPrinter.cpp
Chris Lattner
lattner at cs.uiuc.edu
Wed Feb 1 14:41:23 PST 2006
Changes in directory llvm/lib/CodeGen:
AsmPrinter.cpp updated: 1.44 -> 1.45
---
Log message:
Implement smart printing of inline asm strings, handling variants and
substituted operands. For this testcase:
int %test(int %A, int %B) {
%C = call int asm "xyz $0, $1, $2", "=r,r,r"(int %A, int %B)
ret int %C
}
we now emit:
_test:
or r2, r3, r3
or r3, r4, r4
xyz r2, r2, r3 ;; look here
or r3, r2, r2
blr
... note the substituted operands. :)
---
Diffs of the changes: (+112 -5)
AsmPrinter.cpp | 117 ++++++++++++++++++++++++++++++++++++++++++++++++++++++---
1 files changed, 112 insertions(+), 5 deletions(-)
Index: llvm/lib/CodeGen/AsmPrinter.cpp
diff -u llvm/lib/CodeGen/AsmPrinter.cpp:1.44 llvm/lib/CodeGen/AsmPrinter.cpp:1.45
--- llvm/lib/CodeGen/AsmPrinter.cpp:1.44 Tue Jan 31 19:28:23 2006
+++ llvm/lib/CodeGen/AsmPrinter.cpp Wed Feb 1 16:41:11 2006
@@ -20,6 +20,7 @@
#include "llvm/Support/MathExtras.h"
#include "llvm/Target/TargetMachine.h"
#include <iostream>
+#include <cerrno>
using namespace llvm;
AsmPrinter::AsmPrinter(std::ostream &o, TargetMachine &tm)
@@ -468,12 +469,118 @@
assert(NumDefs != NumOperands-1 && "No asm string?");
assert(MI->getOperand(NumDefs).isExternalSymbol() && "No asm string?");
-
+
+ // Disassemble the AsmStr, printing out the literal pieces, the operands, etc.
const char *AsmStr = MI->getOperand(NumDefs).getSymbolName();
+
+ // The variant of the current asmprinter: FIXME: change.
+ int AsmPrinterVariant = 0;
- O << AsmStr << "\n";
-
- // Use a virtual "printAsmOperand" method, which takes the constraint
- // string? Must pass the constraint string to here if needed.
+ int CurVariant = -1; // The number of the {.|.|.} region we are in.
+ const char *LastEmitted = AsmStr; // One past the last character emitted.
+ while (*LastEmitted) {
+ switch (*LastEmitted) {
+ default: {
+ // Not a special case, emit the string section literally.
+ const char *LiteralEnd = LastEmitted+1;
+ while (*LiteralEnd && *LiteralEnd != '{' && *LiteralEnd != '|' &&
+ *LiteralEnd != '}' && *LiteralEnd != '$')
+ ++LiteralEnd;
+ if (CurVariant == -1 || CurVariant == AsmPrinterVariant)
+ O.write(LastEmitted, LiteralEnd-LastEmitted);
+ LastEmitted = LiteralEnd;
+ break;
+ }
+ case '$': {
+ ++LastEmitted; // Consume '$' character.
+ if (*LastEmitted == '$') { // $$ -> $
+ if (CurVariant == -1 || CurVariant == AsmPrinterVariant)
+ O << '$';
+ ++LastEmitted; // Consume second '$' character.
+ break;
+ }
+
+ bool HasCurlyBraces = false;
+ if (*LastEmitted == '{') { // ${variable}
+ ++LastEmitted; // Consume '{' character.
+ HasCurlyBraces = true;
+ }
+
+ const char *IDStart = LastEmitted;
+ char *IDEnd;
+ long Val = strtol(IDStart, &IDEnd, 10); // We only accept numbers for IDs.
+ if (!isdigit(*IDStart) || (Val == 0 && errno == EINVAL)) {
+ std::cerr << "Bad $ operand number in inline asm string: '"
+ << AsmStr << "'\n";
+ exit(1);
+ }
+ LastEmitted = IDEnd;
+
+ if (HasCurlyBraces) {
+ if (*LastEmitted != '}') {
+ std::cerr << "Bad ${} expression in inline asm string: '"
+ << AsmStr << "'\n";
+ exit(1);
+ }
+ ++LastEmitted; // Consume '}' character.
+ }
+
+ if ((unsigned)Val >= NumOperands-1) {
+ std::cerr << "Invalid $ operand number in inline asm string: '"
+ << AsmStr << "'\n";
+ exit(1);
+ }
+
+ // Okay, we finally have an operand number. Ask the target to print this
+ // operand!
+ if (CurVariant == -1 || CurVariant == AsmPrinterVariant)
+ if (const_cast<AsmPrinter*>(this)->
+ PrintAsmOperand(MI, Val+1, AsmPrinterVariant)) {
+ std::cerr << "Invalid operand found in inline asm: '"
+ << AsmStr << "'\n";
+ MI->dump();
+ exit(1);
+ }
+ break;
+ }
+ case '{':
+ ++LastEmitted; // Consume '{' character.
+ if (CurVariant != -1) {
+ std::cerr << "Nested variants found in inline asm string: '"
+ << AsmStr << "'\n";
+ exit(1);
+ }
+ CurVariant = 0; // We're in the first variant now.
+ break;
+ case '|':
+ ++LastEmitted; // consume '|' character.
+ if (CurVariant == -1) {
+ std::cerr << "Found '|' character outside of variant in inline asm "
+ << "string: '" << AsmStr << "'\n";
+ exit(1);
+ }
+ ++CurVariant; // We're in the next variant.
+ break;
+ case '}':
+ ++LastEmitted; // consume '}' character.
+ if (CurVariant == -1) {
+ std::cerr << "Found '}' character outside of variant in inline asm "
+ << "string: '" << AsmStr << "'\n";
+ exit(1);
+ }
+ CurVariant = -1;
+ break;
+ }
+ }
+ O << "\n";
+}
+
+/// PrintAsmOperand - Print the specified operand of MI, an INLINEASM
+/// instruction, using the specified assembler variant. Targets should
+/// overried this to format as appropriate.
+bool AsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
+ unsigned AsmVariant) {
+ // Target doesn't support this yet!
+ return true;
}
More information about the llvm-commits
mailing list