summaryrefslogtreecommitdiff
path: root/llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2021-11-19 20:06:13 +0000
committerDimitry Andric <dim@FreeBSD.org>2021-11-19 20:06:13 +0000
commitc0981da47d5696fe36474fcf86b4ce03ae3ff818 (patch)
treef42add1021b9f2ac6a69ac7cf6c4499962739a45 /llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp
parent344a3780b2e33f6ca763666c380202b18aab72a3 (diff)
Diffstat (limited to 'llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp')
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp172
1 files changed, 101 insertions, 71 deletions
diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp
index 4a93181f5439..ef1abc47701a 100644
--- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp
@@ -30,10 +30,10 @@
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/MC/MCSymbol.h"
+#include "llvm/MC/TargetRegistry.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/SourceMgr.h"
-#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetMachine.h"
using namespace llvm;
@@ -129,13 +129,16 @@ void AsmPrinter::emitInlineAsm(StringRef Str, const MCSubtargetInfo &STI,
}
static void EmitMSInlineAsmStr(const char *AsmStr, const MachineInstr *MI,
- MachineModuleInfo *MMI, AsmPrinter *AP,
- uint64_t LocCookie, raw_ostream &OS) {
+ MachineModuleInfo *MMI, const MCAsmInfo *MAI,
+ AsmPrinter *AP, uint64_t LocCookie,
+ raw_ostream &OS) {
// Switch to the inline assembly variant.
OS << "\t.intel_syntax\n\t";
+ int CurVariant = -1; // The number of the {.|.|.} region we are in.
const char *LastEmitted = AsmStr; // One past the last character emitted.
unsigned NumOperands = MI->getNumOperands();
+ int AsmPrinterVariant = 1; // X86MCAsmInfo.cpp's AsmWriterFlavorTy::Intel.
while (*LastEmitted) {
switch (*LastEmitted) {
@@ -145,8 +148,8 @@ static void EmitMSInlineAsmStr(const char *AsmStr, const MachineInstr *MI,
while (*LiteralEnd && *LiteralEnd != '{' && *LiteralEnd != '|' &&
*LiteralEnd != '}' && *LiteralEnd != '$' && *LiteralEnd != '\n')
++LiteralEnd;
-
- OS.write(LastEmitted, LiteralEnd-LastEmitted);
+ if (CurVariant == -1 || CurVariant == AsmPrinterVariant)
+ OS.write(LastEmitted, LiteralEnd - LastEmitted);
LastEmitted = LiteralEnd;
break;
}
@@ -164,6 +167,27 @@ static void EmitMSInlineAsmStr(const char *AsmStr, const MachineInstr *MI,
case '$':
++LastEmitted; // Consume second '$' character.
break;
+ case '(': // $( -> same as GCC's { character.
+ ++LastEmitted; // Consume '(' character.
+ if (CurVariant != -1)
+ report_fatal_error("Nested variants found in inline asm string: '" +
+ Twine(AsmStr) + "'");
+ CurVariant = 0; // We're in the first variant now.
+ break;
+ case '|':
+ ++LastEmitted; // Consume '|' character.
+ if (CurVariant == -1)
+ OS << '|'; // This is gcc's behavior for | outside a variant.
+ else
+ ++CurVariant; // We're in the next variant.
+ break;
+ case ')': // $) -> same as GCC's } char.
+ ++LastEmitted; // Consume ')' character.
+ if (CurVariant == -1)
+ OS << '}'; // This is gcc's behavior for } outside a variant.
+ else
+ CurVariant = -1;
+ break;
}
if (Done) break;
@@ -176,16 +200,15 @@ static void EmitMSInlineAsmStr(const char *AsmStr, const MachineInstr *MI,
// If we have ${:foo}, then this is not a real operand reference, it is a
// "magic" string reference, just like in .td files. Arrange to call
// PrintSpecial.
- if (HasCurlyBraces && LastEmitted[0] == ':') {
+ if (HasCurlyBraces && *LastEmitted == ':') {
++LastEmitted;
const char *StrStart = LastEmitted;
const char *StrEnd = strchr(StrStart, '}');
if (!StrEnd)
report_fatal_error("Unterminated ${:foo} operand in inline asm"
" string: '" + Twine(AsmStr) + "'");
-
- std::string Val(StrStart, StrEnd);
- AP->PrintSpecial(MI, OS, Val.c_str());
+ if (CurVariant == -1 || CurVariant == AsmPrinterVariant)
+ AP->PrintSpecial(MI, OS, StringRef(StrStart, StrEnd - StrStart));
LastEmitted = StrEnd+1;
break;
}
@@ -201,7 +224,7 @@ static void EmitMSInlineAsmStr(const char *AsmStr, const MachineInstr *MI,
Twine(AsmStr) + "'");
LastEmitted = IDEnd;
- if (Val >= NumOperands-1)
+ if (Val >= NumOperands - 1)
report_fatal_error("Invalid $ operand number in inline asm string: '" +
Twine(AsmStr) + "'");
@@ -228,40 +251,50 @@ static void EmitMSInlineAsmStr(const char *AsmStr, const MachineInstr *MI,
// Okay, we finally have a value number. Ask the target to print this
// operand!
- unsigned OpNo = InlineAsm::MIOp_FirstOperand;
-
- bool Error = false;
+ if (CurVariant == -1 || CurVariant == AsmPrinterVariant) {
+ unsigned OpNo = InlineAsm::MIOp_FirstOperand;
- // Scan to find the machine operand number for the operand.
- for (; Val; --Val) {
- if (OpNo >= MI->getNumOperands()) break;
- unsigned OpFlags = MI->getOperand(OpNo).getImm();
- OpNo += InlineAsm::getNumOperandRegisters(OpFlags) + 1;
- }
+ bool Error = false;
- // We may have a location metadata attached to the end of the
- // instruction, and at no point should see metadata at any
- // other point while processing. It's an error if so.
- if (OpNo >= MI->getNumOperands() ||
- MI->getOperand(OpNo).isMetadata()) {
- Error = true;
- } else {
- unsigned OpFlags = MI->getOperand(OpNo).getImm();
- ++OpNo; // Skip over the ID number.
+ // Scan to find the machine operand number for the operand.
+ for (; Val; --Val) {
+ if (OpNo >= MI->getNumOperands())
+ break;
+ unsigned OpFlags = MI->getOperand(OpNo).getImm();
+ OpNo += InlineAsm::getNumOperandRegisters(OpFlags) + 1;
+ }
- if (InlineAsm::isMemKind(OpFlags)) {
- Error = AP->PrintAsmMemoryOperand(
- MI, OpNo, Modifier[0] ? Modifier : nullptr, OS);
+ // We may have a location metadata attached to the end of the
+ // instruction, and at no point should see metadata at any
+ // other point while processing. It's an error if so.
+ if (OpNo >= MI->getNumOperands() || MI->getOperand(OpNo).isMetadata()) {
+ Error = true;
} else {
- Error = AP->PrintAsmOperand(MI, OpNo,
- Modifier[0] ? Modifier : nullptr, OS);
+ unsigned OpFlags = MI->getOperand(OpNo).getImm();
+ ++OpNo; // Skip over the ID number.
+
+ // FIXME: Shouldn't arch-independent output template handling go into
+ // PrintAsmOperand?
+ // Labels are target independent.
+ if (MI->getOperand(OpNo).isBlockAddress()) {
+ const BlockAddress *BA = MI->getOperand(OpNo).getBlockAddress();
+ MCSymbol *Sym = AP->GetBlockAddressSymbol(BA);
+ Sym->print(OS, AP->MAI);
+ MMI->getContext().registerInlineAsmLabel(Sym);
+ } else if (InlineAsm::isMemKind(OpFlags)) {
+ Error = AP->PrintAsmMemoryOperand(
+ MI, OpNo, Modifier[0] ? Modifier : nullptr, OS);
+ } else {
+ Error = AP->PrintAsmOperand(MI, OpNo,
+ Modifier[0] ? Modifier : nullptr, OS);
+ }
+ }
+ if (Error) {
+ std::string msg;
+ raw_string_ostream Msg(msg);
+ Msg << "invalid operand in inline asm: '" << AsmStr << "'";
+ MMI->getModule()->getContext().emitError(LocCookie, Msg.str());
}
- }
- if (Error) {
- std::string msg;
- raw_string_ostream Msg(msg);
- Msg << "invalid operand in inline asm: '" << AsmStr << "'";
- MMI->getModule()->getContext().emitError(LocCookie, Msg.str());
}
break;
}
@@ -274,10 +307,10 @@ static void EmitGCCInlineAsmStr(const char *AsmStr, const MachineInstr *MI,
MachineModuleInfo *MMI, const MCAsmInfo *MAI,
AsmPrinter *AP, uint64_t LocCookie,
raw_ostream &OS) {
- int CurVariant = -1; // The number of the {.|.|.} region we are in.
+ int CurVariant = -1; // The number of the {.|.|.} region we are in.
const char *LastEmitted = AsmStr; // One past the last character emitted.
unsigned NumOperands = MI->getNumOperands();
- int AsmPrinterVariant = MAI->getAssemblerDialect();
+ int AsmPrinterVariant = MMI->getTarget().unqualifiedInlineAsmVariant();
if (MAI->getEmitGNUAsmStartIndentationMarker())
OS << '\t';
@@ -291,7 +324,7 @@ static void EmitGCCInlineAsmStr(const char *AsmStr, const MachineInstr *MI,
*LiteralEnd != '}' && *LiteralEnd != '$' && *LiteralEnd != '\n')
++LiteralEnd;
if (CurVariant == -1 || CurVariant == AsmPrinterVariant)
- OS.write(LastEmitted, LiteralEnd-LastEmitted);
+ OS.write(LastEmitted, LiteralEnd - LastEmitted);
LastEmitted = LiteralEnd;
break;
}
@@ -311,24 +344,24 @@ static void EmitGCCInlineAsmStr(const char *AsmStr, const MachineInstr *MI,
OS << '$';
++LastEmitted; // Consume second '$' character.
break;
- case '(': // $( -> same as GCC's { character.
- ++LastEmitted; // Consume '(' character.
+ case '(': // $( -> same as GCC's { character.
+ ++LastEmitted; // Consume '(' character.
if (CurVariant != -1)
report_fatal_error("Nested variants found in inline asm string: '" +
Twine(AsmStr) + "'");
- CurVariant = 0; // We're in the first variant now.
+ CurVariant = 0; // We're in the first variant now.
break;
case '|':
- ++LastEmitted; // consume '|' character.
+ ++LastEmitted; // Consume '|' character.
if (CurVariant == -1)
- OS << '|'; // this is gcc's behavior for | outside a variant
+ OS << '|'; // This is gcc's behavior for | outside a variant.
else
- ++CurVariant; // We're in the next variant.
+ ++CurVariant; // We're in the next variant.
break;
- case ')': // $) -> same as GCC's } char.
- ++LastEmitted; // consume ')' character.
+ case ')': // $) -> same as GCC's } char.
+ ++LastEmitted; // Consume ')' character.
if (CurVariant == -1)
- OS << '}'; // this is gcc's behavior for } outside a variant
+ OS << '}'; // This is gcc's behavior for } outside a variant.
else
CurVariant = -1;
break;
@@ -351,9 +384,8 @@ static void EmitGCCInlineAsmStr(const char *AsmStr, const MachineInstr *MI,
if (!StrEnd)
report_fatal_error("Unterminated ${:foo} operand in inline asm"
" string: '" + Twine(AsmStr) + "'");
-
- std::string Val(StrStart, StrEnd);
- AP->PrintSpecial(MI, OS, Val.c_str());
+ if (CurVariant == -1 || CurVariant == AsmPrinterVariant)
+ AP->PrintSpecial(MI, OS, StringRef(StrStart, StrEnd - StrStart));
LastEmitted = StrEnd+1;
break;
}
@@ -369,6 +401,10 @@ static void EmitGCCInlineAsmStr(const char *AsmStr, const MachineInstr *MI,
Twine(AsmStr) + "'");
LastEmitted = IDEnd;
+ if (Val >= NumOperands - 1)
+ report_fatal_error("Invalid $ operand number in inline asm string: '" +
+ Twine(AsmStr) + "'");
+
char Modifier[2] = { 0, 0 };
if (HasCurlyBraces) {
@@ -390,10 +426,6 @@ static void EmitGCCInlineAsmStr(const char *AsmStr, const MachineInstr *MI,
++LastEmitted; // Consume '}' character.
}
- if (Val >= NumOperands-1)
- report_fatal_error("Invalid $ operand number in inline asm string: '" +
- Twine(AsmStr) + "'");
-
// Okay, we finally have a value number. Ask the target to print this
// operand!
if (CurVariant == -1 || CurVariant == AsmPrinterVariant) {
@@ -403,7 +435,8 @@ static void EmitGCCInlineAsmStr(const char *AsmStr, const MachineInstr *MI,
// Scan to find the machine operand number for the operand.
for (; Val; --Val) {
- if (OpNo >= MI->getNumOperands()) break;
+ if (OpNo >= MI->getNumOperands())
+ break;
unsigned OpFlags = MI->getOperand(OpNo).getImm();
OpNo += InlineAsm::getNumOperandRegisters(OpFlags) + 1;
}
@@ -411,12 +444,11 @@ static void EmitGCCInlineAsmStr(const char *AsmStr, const MachineInstr *MI,
// We may have a location metadata attached to the end of the
// instruction, and at no point should see metadata at any
// other point while processing. It's an error if so.
- if (OpNo >= MI->getNumOperands() ||
- MI->getOperand(OpNo).isMetadata()) {
+ if (OpNo >= MI->getNumOperands() || MI->getOperand(OpNo).isMetadata()) {
Error = true;
} else {
unsigned OpFlags = MI->getOperand(OpNo).getImm();
- ++OpNo; // Skip over the ID number.
+ ++OpNo; // Skip over the ID number.
// FIXME: Shouldn't arch-independent output template handling go into
// PrintAsmOperand?
@@ -429,8 +461,6 @@ static void EmitGCCInlineAsmStr(const char *AsmStr, const MachineInstr *MI,
} else if (MI->getOperand(OpNo).isMBB()) {
const MCSymbol *Sym = MI->getOperand(OpNo).getMBB()->getSymbol();
Sym->print(OS, AP->MAI);
- } else if (Modifier[0] == 'l') {
- Error = true;
} else if (InlineAsm::isMemKind(OpFlags)) {
Error = AP->PrintAsmMemoryOperand(
MI, OpNo, Modifier[0] ? Modifier : nullptr, OS);
@@ -506,7 +536,7 @@ void AsmPrinter::emitInlineAsm(const MachineInstr *MI) const {
if (MI->getInlineAsmDialect() == InlineAsm::AD_ATT)
EmitGCCInlineAsmStr(AsmStr, MI, MMI, MAI, AP, LocCookie, OS);
else
- EmitMSInlineAsmStr(AsmStr, MI, MMI, AP, LocCookie, OS);
+ EmitMSInlineAsmStr(AsmStr, MI, MMI, MAI, AP, LocCookie, OS);
// Emit warnings if we use reserved registers on the clobber list, as
// that might lead to undefined behaviour.
@@ -540,7 +570,7 @@ void AsmPrinter::emitInlineAsm(const MachineInstr *MI) const {
"preserved across the asm statement, and clobbering them may "
"lead to undefined behaviour.";
MMI->getModule()->getContext().diagnose(DiagnosticInfoInlineAsm(
- LocCookie, Msg.c_str(), DiagnosticSeverity::DS_Warning));
+ LocCookie, Msg, DiagnosticSeverity::DS_Warning));
MMI->getModule()->getContext().diagnose(
DiagnosticInfoInlineAsm(LocCookie, Note, DiagnosticSeverity::DS_Note));
}
@@ -560,13 +590,13 @@ void AsmPrinter::emitInlineAsm(const MachineInstr *MI) const {
/// syntax used is ${:comment}. Targets can override this to add support
/// for their own strange codes.
void AsmPrinter::PrintSpecial(const MachineInstr *MI, raw_ostream &OS,
- const char *Code) const {
- if (!strcmp(Code, "private")) {
+ StringRef Code) const {
+ if (Code == "private") {
const DataLayout &DL = MF->getDataLayout();
OS << DL.getPrivateGlobalPrefix();
- } else if (!strcmp(Code, "comment")) {
+ } else if (Code == "comment") {
OS << MAI->getCommentString();
- } else if (!strcmp(Code, "uid")) {
+ } else if (Code == "uid") {
// Comparing the address of MI isn't sufficient, because machineinstrs may
// be allocated to the same address across functions.
@@ -582,7 +612,7 @@ void AsmPrinter::PrintSpecial(const MachineInstr *MI, raw_ostream &OS,
raw_string_ostream Msg(msg);
Msg << "Unknown special formatter '" << Code
<< "' for machine instr: " << *MI;
- report_fatal_error(Msg.str());
+ report_fatal_error(Twine(Msg.str()));
}
}