45#define DEBUG_TYPE "asm-printer"
47unsigned AsmPrinter::addInlineAsmDiagBuffer(
StringRef AsmStr,
48 const MDNode *LocMDNode)
const {
52 std::vector<const MDNode *> &LocInfos = Context.getLocInfos();
54 std::unique_ptr<MemoryBuffer> Buffer;
60 unsigned BufNum =
SrcMgr.AddNewSourceBuffer(std::move(Buffer),
SMLoc());
64 LocInfos.resize(BufNum);
65 LocInfos[BufNum - 1] = LocMDNode;
78 assert(!Str.empty() &&
"Can't emit empty inline asm block");
81 bool isNullTerminated = Str.back() == 0;
83 Str = Str.substr(0, Str.size()-1);
90 const MCAsmInfo *MCAI =
TM.getMCAsmInfo();
91 assert(MCAI &&
"No MCAsmInfo");
101 unsigned BufNum = addInlineAsmDiagBuffer(Str, LocMDNode);
102 SourceMgr &
SrcMgr = *
MMI->getContext().getInlineSourceManager();
110 std::unique_ptr<MCAsmParser> Parser(
117 std::unique_ptr<MCInstrInfo> MII(
TM.getTarget().createMCInstrInfo());
118 assert(MII &&
"Failed to create instruction info");
119 std::unique_ptr<MCTargetAsmParser> TAP(
TM.getTarget().createMCAsmParser(
120 STI, *Parser, *MII, MCOptions));
123 " we don't have an asm parser for this target\n");
126 if (
TM.getTargetTriple().isX86()) {
127 Parser->setAssemblerDialect(Dialect);
131 Parser->getLexer().setLexMasmIntegers(
true);
133 Parser->setTargetParser(*TAP);
137 (void)Parser->Run(
true,
148 if (InputIsIntelDialect) {
150 OS <<
"\t.intel_syntax\n\t";
154 const char *LastEmitted = AsmStr;
155 unsigned NumOperands =
MI->getNumOperands();
157 int AsmPrinterVariant;
158 if (InputIsIntelDialect)
159 AsmPrinterVariant = 1;
164 if (!InputIsIntelDialect && !MAI->
isHLASM())
167 while (*LastEmitted) {
168 switch (*LastEmitted) {
171 const char *LiteralEnd = LastEmitted+1;
172 while (*LiteralEnd && *LiteralEnd !=
'{' && *LiteralEnd !=
'|' &&
173 *LiteralEnd !=
'}' && *LiteralEnd !=
'$' && *LiteralEnd !=
'\n')
175 if (CurVariant == -1 || CurVariant == AsmPrinterVariant)
176 OS.
write(LastEmitted, LiteralEnd - LastEmitted);
177 LastEmitted = LiteralEnd;
189 switch (*LastEmitted) {
190 default:
Done =
false;
break;
192 if (!InputIsIntelDialect)
193 if (CurVariant == -1 || CurVariant == AsmPrinterVariant)
199 if (CurVariant != -1)
201 Twine(AsmStr) +
"'");
206 if (CurVariant == -1)
213 if (CurVariant == -1)
221 bool HasCurlyBraces =
false;
222 if (*LastEmitted ==
'{') {
224 HasCurlyBraces =
true;
230 if (HasCurlyBraces && *LastEmitted ==
':') {
232 const char *StrStart = LastEmitted;
233 const char *StrEnd = strchr(StrStart,
'}');
236 " string: '" +
Twine(AsmStr) +
"'");
237 if (CurVariant == -1 || CurVariant == AsmPrinterVariant)
239 LastEmitted = StrEnd+1;
243 const char *IDStart = LastEmitted;
244 const char *IDEnd = IDStart;
249 if (
StringRef(IDStart, IDEnd-IDStart).getAsInteger(10, Val))
251 Twine(AsmStr) +
"'");
254 if (Val >= NumOperands - 1)
256 Twine(AsmStr) +
"'");
258 char Modifier[2] = { 0, 0 };
260 if (HasCurlyBraces) {
263 if (*LastEmitted ==
':') {
265 if (*LastEmitted == 0)
267 Twine(AsmStr) +
"'");
269 Modifier[0] = *LastEmitted;
273 if (*LastEmitted !=
'}')
275 Twine(AsmStr) +
"'");
281 if (CurVariant == -1 || CurVariant == AsmPrinterVariant) {
288 if (OpNo >=
MI->getNumOperands())
291 OpNo +=
F.getNumOperandRegisters() + 1;
297 if (OpNo >=
MI->getNumOperands() ||
MI->getOperand(OpNo).isMetadata()) {
306 if (
MI->getOperand(OpNo).isBlockAddress()) {
311 }
else if (
MI->getOperand(OpNo).isMBB()) {
312 const MCSymbol *Sym =
MI->getOperand(OpNo).getMBB()->getSymbol();
314 }
else if (
F.isMemKind()) {
316 MI, OpNo, Modifier[0] ? Modifier :
nullptr, OS);
319 Modifier[0] ? Modifier :
nullptr, OS);
323 const Function &Fn =
MI->getMF()->getFunction();
326 "invalid operand in inline asm: '" +
Twine(AsmStr) +
"'"));
333 if (InputIsIntelDialect)
334 OS <<
"\n\t.att_syntax";
335 OS <<
'\n' << (
char)0;
341 assert(
MI->isInlineAsm() &&
"printInlineAsm only works on inline asms");
344 const char *AsmStr =
MI->getOperand(0).getSymbolName();
348 if (AsmStr[0] == 0) {
358 const MDNode *LocMD =
MI->getLocCookieMD();
366 SmallString<256> StringData;
367 raw_svector_ostream OS(StringData);
375 const TargetRegisterInfo *
TRI =
MF->getSubtarget().getRegisterInfo();
379 const MachineOperand &MO =
MI->getOperand(
I);
382 const InlineAsm::Flag
F(MO.
getImm());
383 if (
F.isClobberKind()) {
385 if (!
TRI->isAsmClobberable(*
MF,
Reg))
389 I +=
F.getNumOperandRegisters();
392 if (!RestrRegs.
empty()) {
393 std::string Msg =
"inline asm clobber list contains reserved registers: ";
395 for (
const Register RR : RestrRegs) {
397 Msg +=
TRI->getRegAsmName(RR);
402 "Reserved registers on the clobber list may not be "
403 "preserved across the asm statement, and clobbering them may "
404 "lead to undefined behaviour.";
406 Ctx.
diagnose(DiagnosticInfoInlineAsm(LocCookie, Msg,
411 for (
const Register RR : RestrRegs) {
412 if (std::optional<std::string> reason =
413 TRI->explainReservedReg(*
MF, RR)) {
414 Ctx.
diagnose(DiagnosticInfoInlineAsm(LocCookie, *reason,
421 MI->getInlineAsmDialect(),
MI);
436 if (Code ==
"private") {
438 OS <<
DL.getPrivateGlobalPrefix();
439 }
else if (Code ==
"comment") {
440 OS <<
MAI->getCommentString();
441 }
else if (Code ==
"uid") {
455 Msg <<
"Unknown special formatter '" << Code
456 <<
"' for machine instr: " << *
MI;
474 if (ExtraCode && ExtraCode[0]) {
475 if (ExtraCode[1] != 0)
return true;
479 switch (ExtraCode[0]) {
506 O << ((32 - MO.
getImm()) & 31);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static void EmitInlineAsmStr(const char *AsmStr, const MachineInstr *MI, MachineModuleInfo *MMI, const MCAsmInfo *MAI, AsmPrinter *AP, uint64_t LocCookie, raw_ostream &OS)
This file contains the declarations for the subclasses of Constant, which represent the different fla...
Module.h This file contains the declarations for the Module class.
const size_t AbstractManglingParser< Derived, Alloc >::NumOps
Register const TargetRegisterInfo * TRI
Promote Memory to Register
This file defines the SmallString class.
This file defines the SmallVector class.
Defines the virtual file system interface vfs::FileSystem.
This class is intended to be used as a driving class for all asm writers.
virtual void emitInlineAsmEnd(const MCSubtargetInfo &StartInfo, const MCSubtargetInfo *EndInfo, const MachineInstr *MI)
Let the target do anything it needs to do after emitting inlineasm.
TargetMachine & TM
Target machine description.
virtual void PrintSymbolOperand(const MachineOperand &MO, raw_ostream &OS)
Print the MachineOperand as a symbol.
const MCAsmInfo * MAI
Target Asm Printer information.
MachineFunction * MF
The current machine function.
virtual void PrintSpecial(const MachineInstr *MI, raw_ostream &OS, StringRef Code) const
Print information related to the specified machine instr that is independent of the operand,...
unsigned getFunctionNumber() const
Return a unique ID for the current function.
AsmPrinter(TargetMachine &TM, std::unique_ptr< MCStreamer > Streamer, char &ID=AsmPrinter::ID)
void printOffset(int64_t Offset, raw_ostream &OS) const
This is just convenient handler for printing offsets.
MCSymbol * getSymbolPreferLocal(const GlobalValue &GV) const
Similar to getSymbol() but preferred for references.
MachineModuleInfo * MMI
This is a pointer to the current MachineModuleInfo.
MCContext & OutContext
This is the context for the output file that we are streaming.
std::unique_ptr< MCStreamer > OutStreamer
This is the MCStreamer object for the file we are generating.
virtual bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, const char *ExtraCode, raw_ostream &OS)
Print the specified operand of MI, an INLINEASM instruction, using the specified assembler variant as...
MCSymbol * GetBlockAddressSymbol(const BlockAddress *BA) const
Return the MCSymbol used to satisfy BlockAddress uses of the specified basic block.
const MCSubtargetInfo & getSubtargetInfo() const
Return information about subtarget.
virtual void emitInlineAsmStart() const
Let the target do anything it needs to do before emitting inlineasm.
virtual bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, const char *ExtraCode, raw_ostream &OS)
Print the specified operand of MI, an INLINEASM instruction, using the specified assembler variant.
The address of a basic block.
A parsed version of the target data layout string in and methods for querying it.
Diagnostic information for inline asm reporting.
Lightweight error class with error context and mandatory checking.
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
LLVM_ABI void diagnose(const DiagnosticInfo &DI)
Report a message to the currently installed diagnostic handler.
This class is intended to be used as a base class for asm properties and features specific to the tar...
bool useIntegratedAssembler() const
Return true if assembly (inline or otherwise) should be parsed.
bool parseInlineAsmUsingAsmParser() const
Return true if target want to use AsmParser to parse inlineasm.
Context object for machine code objects.
LLVM_ABI void registerInlineAsmLabel(MCSymbol *Sym)
registerInlineAsmLabel - Records that the name is a label referenced in inline assembly.
LLVM_ABI void initInlineSourceManager()
Generic base class for all target subtargets.
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
LLVM_ABI void print(raw_ostream &OS, const MCAsmInfo *MAI) const
print - Print the value to the stream OS.
std::vector< std::string > IASSearchPaths
Additional paths to search for .include directives when using the integrated assembler.
const MDOperand & getOperand(unsigned I) const
Representation of each machine instruction.
This class contains meta information specific to a module.
const MCContext & getContext() const
const TargetMachine & getTarget() const
MachineOperand class - Representation of each machine instruction operand.
const GlobalValue * getGlobal() const
bool isReg() const
isReg - Tests if this is a MO_Register operand.
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
bool isGlobal() const
isGlobal - Tests if this is a MO_GlobalAddress operand.
int64_t getOffset() const
Return the offset from the symbol in this operand.
static std::unique_ptr< MemoryBuffer > getMemBufferCopy(StringRef InputData, const Twine &BufferName="")
Open the specified memory range as a MemoryBuffer, copying the contents and taking ownership of it.
Represents a location in source code.
void push_back(const T &Elt)
This owns the files read by a parser, handles include stacks, and handles diagnostic wrangling.
void setIncludeDirs(const std::vector< std::string > &Dirs)
LLVM_ABI void setVirtualFileSystem(IntrusiveRefCntPtr< vfs::FileSystem > FS)
StringRef - Represent a constant reference to a string, i.e.
virtual int unqualifiedInlineAsmVariant() const
The default variant to use in unqualified asm instructions.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
This class implements an extremely fast bulk output stream that can only output to a stream.
raw_ostream & write(unsigned char C)
A raw_ostream that writes to an std::string.
std::string & str()
Returns the string's reference.
std::enable_if_t< detail::IsValidPointer< X, Y >::value, X * > extract(Y &&MD)
Extract a Value from Metadata.
ScopedSetting scopedDisable()
LLVM_ABI IntrusiveRefCntPtr< FileSystem > getRealFileSystem()
Gets an vfs::FileSystem for the 'real' file system, as seen by the operating system.
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
bool isDigit(char C)
Checks if character C is one of the 10 decimal digits.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
LLVM_ABI MCAsmParser * createMCAsmParser(SourceMgr &, MCContext &, MCStreamer &, const MCAsmInfo &, unsigned CB=0)
Create an MCAsmParser instance for parsing assembly similar to gas syntax.