diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2021-11-19 20:06:13 +0000 |
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2021-11-19 20:06:13 +0000 |
| commit | c0981da47d5696fe36474fcf86b4ce03ae3ff818 (patch) | |
| tree | f42add1021b9f2ac6a69ac7cf6c4499962739a45 /llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp | |
| parent | 344a3780b2e33f6ca763666c380202b18aab72a3 (diff) | |
Diffstat (limited to 'llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp')
| -rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp | 172 |
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())); } } |
