1*09467b48Spatrick //===-- AsmPrinterInlineAsm.cpp - AsmPrinter Inline Asm Handling ----------===// 2*09467b48Spatrick // 3*09467b48Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*09467b48Spatrick // See https://llvm.org/LICENSE.txt for license information. 5*09467b48Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*09467b48Spatrick // 7*09467b48Spatrick //===----------------------------------------------------------------------===// 8*09467b48Spatrick // 9*09467b48Spatrick // This file implements the inline assembler pieces of the AsmPrinter class. 10*09467b48Spatrick // 11*09467b48Spatrick //===----------------------------------------------------------------------===// 12*09467b48Spatrick 13*09467b48Spatrick #include "llvm/ADT/SmallString.h" 14*09467b48Spatrick #include "llvm/ADT/Twine.h" 15*09467b48Spatrick #include "llvm/CodeGen/AsmPrinter.h" 16*09467b48Spatrick #include "llvm/CodeGen/MachineBasicBlock.h" 17*09467b48Spatrick #include "llvm/CodeGen/MachineFunction.h" 18*09467b48Spatrick #include "llvm/CodeGen/MachineModuleInfo.h" 19*09467b48Spatrick #include "llvm/CodeGen/TargetInstrInfo.h" 20*09467b48Spatrick #include "llvm/CodeGen/TargetRegisterInfo.h" 21*09467b48Spatrick #include "llvm/IR/Constants.h" 22*09467b48Spatrick #include "llvm/IR/DataLayout.h" 23*09467b48Spatrick #include "llvm/IR/InlineAsm.h" 24*09467b48Spatrick #include "llvm/IR/LLVMContext.h" 25*09467b48Spatrick #include "llvm/IR/Module.h" 26*09467b48Spatrick #include "llvm/MC/MCAsmInfo.h" 27*09467b48Spatrick #include "llvm/MC/MCParser/MCTargetAsmParser.h" 28*09467b48Spatrick #include "llvm/MC/MCStreamer.h" 29*09467b48Spatrick #include "llvm/MC/MCSubtargetInfo.h" 30*09467b48Spatrick #include "llvm/MC/MCSymbol.h" 31*09467b48Spatrick #include "llvm/Support/ErrorHandling.h" 32*09467b48Spatrick #include "llvm/Support/MemoryBuffer.h" 33*09467b48Spatrick #include "llvm/Support/SourceMgr.h" 34*09467b48Spatrick #include "llvm/Support/TargetRegistry.h" 35*09467b48Spatrick #include "llvm/Support/raw_ostream.h" 36*09467b48Spatrick #include "llvm/Target/TargetMachine.h" 37*09467b48Spatrick using namespace llvm; 38*09467b48Spatrick 39*09467b48Spatrick #define DEBUG_TYPE "asm-printer" 40*09467b48Spatrick 41*09467b48Spatrick /// srcMgrDiagHandler - This callback is invoked when the SourceMgr for an 42*09467b48Spatrick /// inline asm has an error in it. diagInfo is a pointer to the SrcMgrDiagInfo 43*09467b48Spatrick /// struct above. 44*09467b48Spatrick static void srcMgrDiagHandler(const SMDiagnostic &Diag, void *diagInfo) { 45*09467b48Spatrick AsmPrinter::SrcMgrDiagInfo *DiagInfo = 46*09467b48Spatrick static_cast<AsmPrinter::SrcMgrDiagInfo *>(diagInfo); 47*09467b48Spatrick assert(DiagInfo && "Diagnostic context not passed down?"); 48*09467b48Spatrick 49*09467b48Spatrick // Look up a LocInfo for the buffer this diagnostic is coming from. 50*09467b48Spatrick unsigned BufNum = DiagInfo->SrcMgr.FindBufferContainingLoc(Diag.getLoc()); 51*09467b48Spatrick const MDNode *LocInfo = nullptr; 52*09467b48Spatrick if (BufNum > 0 && BufNum <= DiagInfo->LocInfos.size()) 53*09467b48Spatrick LocInfo = DiagInfo->LocInfos[BufNum-1]; 54*09467b48Spatrick 55*09467b48Spatrick // If the inline asm had metadata associated with it, pull out a location 56*09467b48Spatrick // cookie corresponding to which line the error occurred on. 57*09467b48Spatrick unsigned LocCookie = 0; 58*09467b48Spatrick if (LocInfo) { 59*09467b48Spatrick unsigned ErrorLine = Diag.getLineNo()-1; 60*09467b48Spatrick if (ErrorLine >= LocInfo->getNumOperands()) 61*09467b48Spatrick ErrorLine = 0; 62*09467b48Spatrick 63*09467b48Spatrick if (LocInfo->getNumOperands() != 0) 64*09467b48Spatrick if (const ConstantInt *CI = 65*09467b48Spatrick mdconst::dyn_extract<ConstantInt>(LocInfo->getOperand(ErrorLine))) 66*09467b48Spatrick LocCookie = CI->getZExtValue(); 67*09467b48Spatrick } 68*09467b48Spatrick 69*09467b48Spatrick DiagInfo->DiagHandler(Diag, DiagInfo->DiagContext, LocCookie); 70*09467b48Spatrick } 71*09467b48Spatrick 72*09467b48Spatrick unsigned AsmPrinter::addInlineAsmDiagBuffer(StringRef AsmStr, 73*09467b48Spatrick const MDNode *LocMDNode) const { 74*09467b48Spatrick if (!DiagInfo) { 75*09467b48Spatrick DiagInfo = std::make_unique<SrcMgrDiagInfo>(); 76*09467b48Spatrick 77*09467b48Spatrick MCContext &Context = MMI->getContext(); 78*09467b48Spatrick Context.setInlineSourceManager(&DiagInfo->SrcMgr); 79*09467b48Spatrick 80*09467b48Spatrick LLVMContext &LLVMCtx = MMI->getModule()->getContext(); 81*09467b48Spatrick if (LLVMCtx.getInlineAsmDiagnosticHandler()) { 82*09467b48Spatrick DiagInfo->DiagHandler = LLVMCtx.getInlineAsmDiagnosticHandler(); 83*09467b48Spatrick DiagInfo->DiagContext = LLVMCtx.getInlineAsmDiagnosticContext(); 84*09467b48Spatrick DiagInfo->SrcMgr.setDiagHandler(srcMgrDiagHandler, DiagInfo.get()); 85*09467b48Spatrick } 86*09467b48Spatrick } 87*09467b48Spatrick 88*09467b48Spatrick SourceMgr &SrcMgr = DiagInfo->SrcMgr; 89*09467b48Spatrick 90*09467b48Spatrick std::unique_ptr<MemoryBuffer> Buffer; 91*09467b48Spatrick // The inline asm source manager will outlive AsmStr, so make a copy of the 92*09467b48Spatrick // string for SourceMgr to own. 93*09467b48Spatrick Buffer = MemoryBuffer::getMemBufferCopy(AsmStr, "<inline asm>"); 94*09467b48Spatrick 95*09467b48Spatrick // Tell SrcMgr about this buffer, it takes ownership of the buffer. 96*09467b48Spatrick unsigned BufNum = SrcMgr.AddNewSourceBuffer(std::move(Buffer), SMLoc()); 97*09467b48Spatrick 98*09467b48Spatrick // Store LocMDNode in DiagInfo, using BufNum as an identifier. 99*09467b48Spatrick if (LocMDNode) { 100*09467b48Spatrick DiagInfo->LocInfos.resize(BufNum); 101*09467b48Spatrick DiagInfo->LocInfos[BufNum - 1] = LocMDNode; 102*09467b48Spatrick } 103*09467b48Spatrick 104*09467b48Spatrick return BufNum; 105*09467b48Spatrick } 106*09467b48Spatrick 107*09467b48Spatrick 108*09467b48Spatrick /// EmitInlineAsm - Emit a blob of inline asm to the output streamer. 109*09467b48Spatrick void AsmPrinter::EmitInlineAsm(StringRef Str, const MCSubtargetInfo &STI, 110*09467b48Spatrick const MCTargetOptions &MCOptions, 111*09467b48Spatrick const MDNode *LocMDNode, 112*09467b48Spatrick InlineAsm::AsmDialect Dialect) const { 113*09467b48Spatrick assert(!Str.empty() && "Can't emit empty inline asm block"); 114*09467b48Spatrick 115*09467b48Spatrick // Remember if the buffer is nul terminated or not so we can avoid a copy. 116*09467b48Spatrick bool isNullTerminated = Str.back() == 0; 117*09467b48Spatrick if (isNullTerminated) 118*09467b48Spatrick Str = Str.substr(0, Str.size()-1); 119*09467b48Spatrick 120*09467b48Spatrick // If the output streamer does not have mature MC support or the integrated 121*09467b48Spatrick // assembler has been disabled, just emit the blob textually. 122*09467b48Spatrick // Otherwise parse the asm and emit it via MC support. 123*09467b48Spatrick // This is useful in case the asm parser doesn't handle something but the 124*09467b48Spatrick // system assembler does. 125*09467b48Spatrick const MCAsmInfo *MCAI = TM.getMCAsmInfo(); 126*09467b48Spatrick assert(MCAI && "No MCAsmInfo"); 127*09467b48Spatrick if (!MCAI->useIntegratedAssembler() && 128*09467b48Spatrick !OutStreamer->isIntegratedAssemblerRequired()) { 129*09467b48Spatrick emitInlineAsmStart(); 130*09467b48Spatrick OutStreamer->EmitRawText(Str); 131*09467b48Spatrick emitInlineAsmEnd(STI, nullptr); 132*09467b48Spatrick return; 133*09467b48Spatrick } 134*09467b48Spatrick 135*09467b48Spatrick unsigned BufNum = addInlineAsmDiagBuffer(Str, LocMDNode); 136*09467b48Spatrick DiagInfo->SrcMgr.setIncludeDirs(MCOptions.IASSearchPaths); 137*09467b48Spatrick 138*09467b48Spatrick std::unique_ptr<MCAsmParser> Parser(createMCAsmParser( 139*09467b48Spatrick DiagInfo->SrcMgr, OutContext, *OutStreamer, *MAI, BufNum)); 140*09467b48Spatrick 141*09467b48Spatrick // Do not use assembler-level information for parsing inline assembly. 142*09467b48Spatrick OutStreamer->setUseAssemblerInfoForParsing(false); 143*09467b48Spatrick 144*09467b48Spatrick // We create a new MCInstrInfo here since we might be at the module level 145*09467b48Spatrick // and not have a MachineFunction to initialize the TargetInstrInfo from and 146*09467b48Spatrick // we only need MCInstrInfo for asm parsing. We create one unconditionally 147*09467b48Spatrick // because it's not subtarget dependent. 148*09467b48Spatrick std::unique_ptr<MCInstrInfo> MII(TM.getTarget().createMCInstrInfo()); 149*09467b48Spatrick std::unique_ptr<MCTargetAsmParser> TAP(TM.getTarget().createMCAsmParser( 150*09467b48Spatrick STI, *Parser, *MII, MCOptions)); 151*09467b48Spatrick if (!TAP) 152*09467b48Spatrick report_fatal_error("Inline asm not supported by this streamer because" 153*09467b48Spatrick " we don't have an asm parser for this target\n"); 154*09467b48Spatrick Parser->setAssemblerDialect(Dialect); 155*09467b48Spatrick Parser->setTargetParser(*TAP.get()); 156*09467b48Spatrick // Enable lexing Masm binary and hex integer literals in intel inline 157*09467b48Spatrick // assembly. 158*09467b48Spatrick if (Dialect == InlineAsm::AD_Intel) 159*09467b48Spatrick Parser->getLexer().setLexMasmIntegers(true); 160*09467b48Spatrick 161*09467b48Spatrick emitInlineAsmStart(); 162*09467b48Spatrick // Don't implicitly switch to the text section before the asm. 163*09467b48Spatrick int Res = Parser->Run(/*NoInitialTextSection*/ true, 164*09467b48Spatrick /*NoFinalize*/ true); 165*09467b48Spatrick emitInlineAsmEnd(STI, &TAP->getSTI()); 166*09467b48Spatrick 167*09467b48Spatrick if (Res && !DiagInfo->DiagHandler) 168*09467b48Spatrick report_fatal_error("Error parsing inline asm\n"); 169*09467b48Spatrick } 170*09467b48Spatrick 171*09467b48Spatrick static void EmitMSInlineAsmStr(const char *AsmStr, const MachineInstr *MI, 172*09467b48Spatrick MachineModuleInfo *MMI, AsmPrinter *AP, 173*09467b48Spatrick unsigned LocCookie, raw_ostream &OS) { 174*09467b48Spatrick // Switch to the inline assembly variant. 175*09467b48Spatrick OS << "\t.intel_syntax\n\t"; 176*09467b48Spatrick 177*09467b48Spatrick const char *LastEmitted = AsmStr; // One past the last character emitted. 178*09467b48Spatrick unsigned NumOperands = MI->getNumOperands(); 179*09467b48Spatrick 180*09467b48Spatrick while (*LastEmitted) { 181*09467b48Spatrick switch (*LastEmitted) { 182*09467b48Spatrick default: { 183*09467b48Spatrick // Not a special case, emit the string section literally. 184*09467b48Spatrick const char *LiteralEnd = LastEmitted+1; 185*09467b48Spatrick while (*LiteralEnd && *LiteralEnd != '{' && *LiteralEnd != '|' && 186*09467b48Spatrick *LiteralEnd != '}' && *LiteralEnd != '$' && *LiteralEnd != '\n') 187*09467b48Spatrick ++LiteralEnd; 188*09467b48Spatrick 189*09467b48Spatrick OS.write(LastEmitted, LiteralEnd-LastEmitted); 190*09467b48Spatrick LastEmitted = LiteralEnd; 191*09467b48Spatrick break; 192*09467b48Spatrick } 193*09467b48Spatrick case '\n': 194*09467b48Spatrick ++LastEmitted; // Consume newline character. 195*09467b48Spatrick OS << '\n'; // Indent code with newline. 196*09467b48Spatrick break; 197*09467b48Spatrick case '$': { 198*09467b48Spatrick ++LastEmitted; // Consume '$' character. 199*09467b48Spatrick bool Done = true; 200*09467b48Spatrick 201*09467b48Spatrick // Handle escapes. 202*09467b48Spatrick switch (*LastEmitted) { 203*09467b48Spatrick default: Done = false; break; 204*09467b48Spatrick case '$': 205*09467b48Spatrick ++LastEmitted; // Consume second '$' character. 206*09467b48Spatrick break; 207*09467b48Spatrick } 208*09467b48Spatrick if (Done) break; 209*09467b48Spatrick 210*09467b48Spatrick bool HasCurlyBraces = false; 211*09467b48Spatrick if (*LastEmitted == '{') { // ${variable} 212*09467b48Spatrick ++LastEmitted; // Consume '{' character. 213*09467b48Spatrick HasCurlyBraces = true; 214*09467b48Spatrick } 215*09467b48Spatrick 216*09467b48Spatrick // If we have ${:foo}, then this is not a real operand reference, it is a 217*09467b48Spatrick // "magic" string reference, just like in .td files. Arrange to call 218*09467b48Spatrick // PrintSpecial. 219*09467b48Spatrick if (HasCurlyBraces && LastEmitted[0] == ':') { 220*09467b48Spatrick ++LastEmitted; 221*09467b48Spatrick const char *StrStart = LastEmitted; 222*09467b48Spatrick const char *StrEnd = strchr(StrStart, '}'); 223*09467b48Spatrick if (!StrEnd) 224*09467b48Spatrick report_fatal_error("Unterminated ${:foo} operand in inline asm" 225*09467b48Spatrick " string: '" + Twine(AsmStr) + "'"); 226*09467b48Spatrick 227*09467b48Spatrick std::string Val(StrStart, StrEnd); 228*09467b48Spatrick AP->PrintSpecial(MI, OS, Val.c_str()); 229*09467b48Spatrick LastEmitted = StrEnd+1; 230*09467b48Spatrick break; 231*09467b48Spatrick } 232*09467b48Spatrick 233*09467b48Spatrick const char *IDStart = LastEmitted; 234*09467b48Spatrick const char *IDEnd = IDStart; 235*09467b48Spatrick while (*IDEnd >= '0' && *IDEnd <= '9') ++IDEnd; 236*09467b48Spatrick 237*09467b48Spatrick unsigned Val; 238*09467b48Spatrick if (StringRef(IDStart, IDEnd-IDStart).getAsInteger(10, Val)) 239*09467b48Spatrick report_fatal_error("Bad $ operand number in inline asm string: '" + 240*09467b48Spatrick Twine(AsmStr) + "'"); 241*09467b48Spatrick LastEmitted = IDEnd; 242*09467b48Spatrick 243*09467b48Spatrick if (Val >= NumOperands-1) 244*09467b48Spatrick report_fatal_error("Invalid $ operand number in inline asm string: '" + 245*09467b48Spatrick Twine(AsmStr) + "'"); 246*09467b48Spatrick 247*09467b48Spatrick char Modifier[2] = { 0, 0 }; 248*09467b48Spatrick 249*09467b48Spatrick if (HasCurlyBraces) { 250*09467b48Spatrick // If we have curly braces, check for a modifier character. This 251*09467b48Spatrick // supports syntax like ${0:u}, which correspond to "%u0" in GCC asm. 252*09467b48Spatrick if (*LastEmitted == ':') { 253*09467b48Spatrick ++LastEmitted; // Consume ':' character. 254*09467b48Spatrick if (*LastEmitted == 0) 255*09467b48Spatrick report_fatal_error("Bad ${:} expression in inline asm string: '" + 256*09467b48Spatrick Twine(AsmStr) + "'"); 257*09467b48Spatrick 258*09467b48Spatrick Modifier[0] = *LastEmitted; 259*09467b48Spatrick ++LastEmitted; // Consume modifier character. 260*09467b48Spatrick } 261*09467b48Spatrick 262*09467b48Spatrick if (*LastEmitted != '}') 263*09467b48Spatrick report_fatal_error("Bad ${} expression in inline asm string: '" + 264*09467b48Spatrick Twine(AsmStr) + "'"); 265*09467b48Spatrick ++LastEmitted; // Consume '}' character. 266*09467b48Spatrick } 267*09467b48Spatrick 268*09467b48Spatrick // Okay, we finally have a value number. Ask the target to print this 269*09467b48Spatrick // operand! 270*09467b48Spatrick unsigned OpNo = InlineAsm::MIOp_FirstOperand; 271*09467b48Spatrick 272*09467b48Spatrick bool Error = false; 273*09467b48Spatrick 274*09467b48Spatrick // Scan to find the machine operand number for the operand. 275*09467b48Spatrick for (; Val; --Val) { 276*09467b48Spatrick if (OpNo >= MI->getNumOperands()) break; 277*09467b48Spatrick unsigned OpFlags = MI->getOperand(OpNo).getImm(); 278*09467b48Spatrick OpNo += InlineAsm::getNumOperandRegisters(OpFlags) + 1; 279*09467b48Spatrick } 280*09467b48Spatrick 281*09467b48Spatrick // We may have a location metadata attached to the end of the 282*09467b48Spatrick // instruction, and at no point should see metadata at any 283*09467b48Spatrick // other point while processing. It's an error if so. 284*09467b48Spatrick if (OpNo >= MI->getNumOperands() || 285*09467b48Spatrick MI->getOperand(OpNo).isMetadata()) { 286*09467b48Spatrick Error = true; 287*09467b48Spatrick } else { 288*09467b48Spatrick unsigned OpFlags = MI->getOperand(OpNo).getImm(); 289*09467b48Spatrick ++OpNo; // Skip over the ID number. 290*09467b48Spatrick 291*09467b48Spatrick if (InlineAsm::isMemKind(OpFlags)) { 292*09467b48Spatrick Error = AP->PrintAsmMemoryOperand( 293*09467b48Spatrick MI, OpNo, Modifier[0] ? Modifier : nullptr, OS); 294*09467b48Spatrick } else { 295*09467b48Spatrick Error = AP->PrintAsmOperand(MI, OpNo, 296*09467b48Spatrick Modifier[0] ? Modifier : nullptr, OS); 297*09467b48Spatrick } 298*09467b48Spatrick } 299*09467b48Spatrick if (Error) { 300*09467b48Spatrick std::string msg; 301*09467b48Spatrick raw_string_ostream Msg(msg); 302*09467b48Spatrick Msg << "invalid operand in inline asm: '" << AsmStr << "'"; 303*09467b48Spatrick MMI->getModule()->getContext().emitError(LocCookie, Msg.str()); 304*09467b48Spatrick } 305*09467b48Spatrick break; 306*09467b48Spatrick } 307*09467b48Spatrick } 308*09467b48Spatrick } 309*09467b48Spatrick OS << "\n\t.att_syntax\n" << (char)0; // null terminate string. 310*09467b48Spatrick } 311*09467b48Spatrick 312*09467b48Spatrick static void EmitGCCInlineAsmStr(const char *AsmStr, const MachineInstr *MI, 313*09467b48Spatrick MachineModuleInfo *MMI, int AsmPrinterVariant, 314*09467b48Spatrick AsmPrinter *AP, unsigned LocCookie, 315*09467b48Spatrick raw_ostream &OS) { 316*09467b48Spatrick int CurVariant = -1; // The number of the {.|.|.} region we are in. 317*09467b48Spatrick const char *LastEmitted = AsmStr; // One past the last character emitted. 318*09467b48Spatrick unsigned NumOperands = MI->getNumOperands(); 319*09467b48Spatrick 320*09467b48Spatrick OS << '\t'; 321*09467b48Spatrick 322*09467b48Spatrick while (*LastEmitted) { 323*09467b48Spatrick switch (*LastEmitted) { 324*09467b48Spatrick default: { 325*09467b48Spatrick // Not a special case, emit the string section literally. 326*09467b48Spatrick const char *LiteralEnd = LastEmitted+1; 327*09467b48Spatrick while (*LiteralEnd && *LiteralEnd != '{' && *LiteralEnd != '|' && 328*09467b48Spatrick *LiteralEnd != '}' && *LiteralEnd != '$' && *LiteralEnd != '\n') 329*09467b48Spatrick ++LiteralEnd; 330*09467b48Spatrick if (CurVariant == -1 || CurVariant == AsmPrinterVariant) 331*09467b48Spatrick OS.write(LastEmitted, LiteralEnd-LastEmitted); 332*09467b48Spatrick LastEmitted = LiteralEnd; 333*09467b48Spatrick break; 334*09467b48Spatrick } 335*09467b48Spatrick case '\n': 336*09467b48Spatrick ++LastEmitted; // Consume newline character. 337*09467b48Spatrick OS << '\n'; // Indent code with newline. 338*09467b48Spatrick break; 339*09467b48Spatrick case '$': { 340*09467b48Spatrick ++LastEmitted; // Consume '$' character. 341*09467b48Spatrick bool Done = true; 342*09467b48Spatrick 343*09467b48Spatrick // Handle escapes. 344*09467b48Spatrick switch (*LastEmitted) { 345*09467b48Spatrick default: Done = false; break; 346*09467b48Spatrick case '$': // $$ -> $ 347*09467b48Spatrick if (CurVariant == -1 || CurVariant == AsmPrinterVariant) 348*09467b48Spatrick OS << '$'; 349*09467b48Spatrick ++LastEmitted; // Consume second '$' character. 350*09467b48Spatrick break; 351*09467b48Spatrick case '(': // $( -> same as GCC's { character. 352*09467b48Spatrick ++LastEmitted; // Consume '(' character. 353*09467b48Spatrick if (CurVariant != -1) 354*09467b48Spatrick report_fatal_error("Nested variants found in inline asm string: '" + 355*09467b48Spatrick Twine(AsmStr) + "'"); 356*09467b48Spatrick CurVariant = 0; // We're in the first variant now. 357*09467b48Spatrick break; 358*09467b48Spatrick case '|': 359*09467b48Spatrick ++LastEmitted; // consume '|' character. 360*09467b48Spatrick if (CurVariant == -1) 361*09467b48Spatrick OS << '|'; // this is gcc's behavior for | outside a variant 362*09467b48Spatrick else 363*09467b48Spatrick ++CurVariant; // We're in the next variant. 364*09467b48Spatrick break; 365*09467b48Spatrick case ')': // $) -> same as GCC's } char. 366*09467b48Spatrick ++LastEmitted; // consume ')' character. 367*09467b48Spatrick if (CurVariant == -1) 368*09467b48Spatrick OS << '}'; // this is gcc's behavior for } outside a variant 369*09467b48Spatrick else 370*09467b48Spatrick CurVariant = -1; 371*09467b48Spatrick break; 372*09467b48Spatrick } 373*09467b48Spatrick if (Done) break; 374*09467b48Spatrick 375*09467b48Spatrick bool HasCurlyBraces = false; 376*09467b48Spatrick if (*LastEmitted == '{') { // ${variable} 377*09467b48Spatrick ++LastEmitted; // Consume '{' character. 378*09467b48Spatrick HasCurlyBraces = true; 379*09467b48Spatrick } 380*09467b48Spatrick 381*09467b48Spatrick // If we have ${:foo}, then this is not a real operand reference, it is a 382*09467b48Spatrick // "magic" string reference, just like in .td files. Arrange to call 383*09467b48Spatrick // PrintSpecial. 384*09467b48Spatrick if (HasCurlyBraces && *LastEmitted == ':') { 385*09467b48Spatrick ++LastEmitted; 386*09467b48Spatrick const char *StrStart = LastEmitted; 387*09467b48Spatrick const char *StrEnd = strchr(StrStart, '}'); 388*09467b48Spatrick if (!StrEnd) 389*09467b48Spatrick report_fatal_error("Unterminated ${:foo} operand in inline asm" 390*09467b48Spatrick " string: '" + Twine(AsmStr) + "'"); 391*09467b48Spatrick 392*09467b48Spatrick std::string Val(StrStart, StrEnd); 393*09467b48Spatrick AP->PrintSpecial(MI, OS, Val.c_str()); 394*09467b48Spatrick LastEmitted = StrEnd+1; 395*09467b48Spatrick break; 396*09467b48Spatrick } 397*09467b48Spatrick 398*09467b48Spatrick const char *IDStart = LastEmitted; 399*09467b48Spatrick const char *IDEnd = IDStart; 400*09467b48Spatrick while (*IDEnd >= '0' && *IDEnd <= '9') ++IDEnd; 401*09467b48Spatrick 402*09467b48Spatrick unsigned Val; 403*09467b48Spatrick if (StringRef(IDStart, IDEnd-IDStart).getAsInteger(10, Val)) 404*09467b48Spatrick report_fatal_error("Bad $ operand number in inline asm string: '" + 405*09467b48Spatrick Twine(AsmStr) + "'"); 406*09467b48Spatrick LastEmitted = IDEnd; 407*09467b48Spatrick 408*09467b48Spatrick char Modifier[2] = { 0, 0 }; 409*09467b48Spatrick 410*09467b48Spatrick if (HasCurlyBraces) { 411*09467b48Spatrick // If we have curly braces, check for a modifier character. This 412*09467b48Spatrick // supports syntax like ${0:u}, which correspond to "%u0" in GCC asm. 413*09467b48Spatrick if (*LastEmitted == ':') { 414*09467b48Spatrick ++LastEmitted; // Consume ':' character. 415*09467b48Spatrick if (*LastEmitted == 0) 416*09467b48Spatrick report_fatal_error("Bad ${:} expression in inline asm string: '" + 417*09467b48Spatrick Twine(AsmStr) + "'"); 418*09467b48Spatrick 419*09467b48Spatrick Modifier[0] = *LastEmitted; 420*09467b48Spatrick ++LastEmitted; // Consume modifier character. 421*09467b48Spatrick } 422*09467b48Spatrick 423*09467b48Spatrick if (*LastEmitted != '}') 424*09467b48Spatrick report_fatal_error("Bad ${} expression in inline asm string: '" + 425*09467b48Spatrick Twine(AsmStr) + "'"); 426*09467b48Spatrick ++LastEmitted; // Consume '}' character. 427*09467b48Spatrick } 428*09467b48Spatrick 429*09467b48Spatrick if (Val >= NumOperands-1) 430*09467b48Spatrick report_fatal_error("Invalid $ operand number in inline asm string: '" + 431*09467b48Spatrick Twine(AsmStr) + "'"); 432*09467b48Spatrick 433*09467b48Spatrick // Okay, we finally have a value number. Ask the target to print this 434*09467b48Spatrick // operand! 435*09467b48Spatrick if (CurVariant == -1 || CurVariant == AsmPrinterVariant) { 436*09467b48Spatrick unsigned OpNo = InlineAsm::MIOp_FirstOperand; 437*09467b48Spatrick 438*09467b48Spatrick bool Error = false; 439*09467b48Spatrick 440*09467b48Spatrick // Scan to find the machine operand number for the operand. 441*09467b48Spatrick for (; Val; --Val) { 442*09467b48Spatrick if (OpNo >= MI->getNumOperands()) break; 443*09467b48Spatrick unsigned OpFlags = MI->getOperand(OpNo).getImm(); 444*09467b48Spatrick OpNo += InlineAsm::getNumOperandRegisters(OpFlags) + 1; 445*09467b48Spatrick } 446*09467b48Spatrick 447*09467b48Spatrick // We may have a location metadata attached to the end of the 448*09467b48Spatrick // instruction, and at no point should see metadata at any 449*09467b48Spatrick // other point while processing. It's an error if so. 450*09467b48Spatrick if (OpNo >= MI->getNumOperands() || 451*09467b48Spatrick MI->getOperand(OpNo).isMetadata()) { 452*09467b48Spatrick Error = true; 453*09467b48Spatrick } else { 454*09467b48Spatrick unsigned OpFlags = MI->getOperand(OpNo).getImm(); 455*09467b48Spatrick ++OpNo; // Skip over the ID number. 456*09467b48Spatrick 457*09467b48Spatrick // FIXME: Shouldn't arch-independent output template handling go into 458*09467b48Spatrick // PrintAsmOperand? 459*09467b48Spatrick // Labels are target independent. 460*09467b48Spatrick if (MI->getOperand(OpNo).isBlockAddress()) { 461*09467b48Spatrick const BlockAddress *BA = MI->getOperand(OpNo).getBlockAddress(); 462*09467b48Spatrick MCSymbol *Sym = AP->GetBlockAddressSymbol(BA); 463*09467b48Spatrick Sym->print(OS, AP->MAI); 464*09467b48Spatrick MMI->getContext().registerInlineAsmLabel(Sym); 465*09467b48Spatrick } else if (MI->getOperand(OpNo).isMBB()) { 466*09467b48Spatrick const MCSymbol *Sym = MI->getOperand(OpNo).getMBB()->getSymbol(); 467*09467b48Spatrick Sym->print(OS, AP->MAI); 468*09467b48Spatrick } else if (Modifier[0] == 'l') { 469*09467b48Spatrick Error = true; 470*09467b48Spatrick } else if (InlineAsm::isMemKind(OpFlags)) { 471*09467b48Spatrick Error = AP->PrintAsmMemoryOperand( 472*09467b48Spatrick MI, OpNo, Modifier[0] ? Modifier : nullptr, OS); 473*09467b48Spatrick } else { 474*09467b48Spatrick Error = AP->PrintAsmOperand(MI, OpNo, 475*09467b48Spatrick Modifier[0] ? Modifier : nullptr, OS); 476*09467b48Spatrick } 477*09467b48Spatrick } 478*09467b48Spatrick if (Error) { 479*09467b48Spatrick std::string msg; 480*09467b48Spatrick raw_string_ostream Msg(msg); 481*09467b48Spatrick Msg << "invalid operand in inline asm: '" << AsmStr << "'"; 482*09467b48Spatrick MMI->getModule()->getContext().emitError(LocCookie, Msg.str()); 483*09467b48Spatrick } 484*09467b48Spatrick } 485*09467b48Spatrick break; 486*09467b48Spatrick } 487*09467b48Spatrick } 488*09467b48Spatrick } 489*09467b48Spatrick OS << '\n' << (char)0; // null terminate string. 490*09467b48Spatrick } 491*09467b48Spatrick 492*09467b48Spatrick /// EmitInlineAsm - This method formats and emits the specified machine 493*09467b48Spatrick /// instruction that is an inline asm. 494*09467b48Spatrick void AsmPrinter::EmitInlineAsm(const MachineInstr *MI) const { 495*09467b48Spatrick assert(MI->isInlineAsm() && "printInlineAsm only works on inline asms"); 496*09467b48Spatrick 497*09467b48Spatrick // Count the number of register definitions to find the asm string. 498*09467b48Spatrick unsigned NumDefs = 0; 499*09467b48Spatrick for (; MI->getOperand(NumDefs).isReg() && MI->getOperand(NumDefs).isDef(); 500*09467b48Spatrick ++NumDefs) 501*09467b48Spatrick assert(NumDefs != MI->getNumOperands()-2 && "No asm string?"); 502*09467b48Spatrick 503*09467b48Spatrick assert(MI->getOperand(NumDefs).isSymbol() && "No asm string?"); 504*09467b48Spatrick 505*09467b48Spatrick // Disassemble the AsmStr, printing out the literal pieces, the operands, etc. 506*09467b48Spatrick const char *AsmStr = MI->getOperand(NumDefs).getSymbolName(); 507*09467b48Spatrick 508*09467b48Spatrick // If this asmstr is empty, just print the #APP/#NOAPP markers. 509*09467b48Spatrick // These are useful to see where empty asm's wound up. 510*09467b48Spatrick if (AsmStr[0] == 0) { 511*09467b48Spatrick OutStreamer->emitRawComment(MAI->getInlineAsmStart()); 512*09467b48Spatrick OutStreamer->emitRawComment(MAI->getInlineAsmEnd()); 513*09467b48Spatrick return; 514*09467b48Spatrick } 515*09467b48Spatrick 516*09467b48Spatrick // Emit the #APP start marker. This has to happen even if verbose-asm isn't 517*09467b48Spatrick // enabled, so we use emitRawComment. 518*09467b48Spatrick OutStreamer->emitRawComment(MAI->getInlineAsmStart()); 519*09467b48Spatrick 520*09467b48Spatrick // Get the !srcloc metadata node if we have it, and decode the loc cookie from 521*09467b48Spatrick // it. 522*09467b48Spatrick unsigned LocCookie = 0; 523*09467b48Spatrick const MDNode *LocMD = nullptr; 524*09467b48Spatrick for (unsigned i = MI->getNumOperands(); i != 0; --i) { 525*09467b48Spatrick if (MI->getOperand(i-1).isMetadata() && 526*09467b48Spatrick (LocMD = MI->getOperand(i-1).getMetadata()) && 527*09467b48Spatrick LocMD->getNumOperands() != 0) { 528*09467b48Spatrick if (const ConstantInt *CI = 529*09467b48Spatrick mdconst::dyn_extract<ConstantInt>(LocMD->getOperand(0))) { 530*09467b48Spatrick LocCookie = CI->getZExtValue(); 531*09467b48Spatrick break; 532*09467b48Spatrick } 533*09467b48Spatrick } 534*09467b48Spatrick } 535*09467b48Spatrick 536*09467b48Spatrick // Emit the inline asm to a temporary string so we can emit it through 537*09467b48Spatrick // EmitInlineAsm. 538*09467b48Spatrick SmallString<256> StringData; 539*09467b48Spatrick raw_svector_ostream OS(StringData); 540*09467b48Spatrick 541*09467b48Spatrick // The variant of the current asmprinter. 542*09467b48Spatrick int AsmPrinterVariant = MAI->getAssemblerDialect(); 543*09467b48Spatrick AsmPrinter *AP = const_cast<AsmPrinter*>(this); 544*09467b48Spatrick if (MI->getInlineAsmDialect() == InlineAsm::AD_ATT) 545*09467b48Spatrick EmitGCCInlineAsmStr(AsmStr, MI, MMI, AsmPrinterVariant, AP, LocCookie, OS); 546*09467b48Spatrick else 547*09467b48Spatrick EmitMSInlineAsmStr(AsmStr, MI, MMI, AP, LocCookie, OS); 548*09467b48Spatrick 549*09467b48Spatrick // Emit warnings if we use reserved registers on the clobber list, as 550*09467b48Spatrick // that might give surprising results. 551*09467b48Spatrick std::vector<std::string> RestrRegs; 552*09467b48Spatrick // Start with the first operand descriptor, and iterate over them. 553*09467b48Spatrick for (unsigned I = InlineAsm::MIOp_FirstOperand, NumOps = MI->getNumOperands(); 554*09467b48Spatrick I < NumOps; ++I) { 555*09467b48Spatrick const MachineOperand &MO = MI->getOperand(I); 556*09467b48Spatrick if (MO.isImm()) { 557*09467b48Spatrick unsigned Flags = MO.getImm(); 558*09467b48Spatrick const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo(); 559*09467b48Spatrick if (InlineAsm::getKind(Flags) == InlineAsm::Kind_Clobber && 560*09467b48Spatrick !TRI->isAsmClobberable(*MF, MI->getOperand(I + 1).getReg())) { 561*09467b48Spatrick RestrRegs.push_back(TRI->getName(MI->getOperand(I + 1).getReg())); 562*09467b48Spatrick } 563*09467b48Spatrick // Skip to one before the next operand descriptor, if it exists. 564*09467b48Spatrick I += InlineAsm::getNumOperandRegisters(Flags); 565*09467b48Spatrick } 566*09467b48Spatrick } 567*09467b48Spatrick 568*09467b48Spatrick if (!RestrRegs.empty()) { 569*09467b48Spatrick unsigned BufNum = addInlineAsmDiagBuffer(OS.str(), LocMD); 570*09467b48Spatrick auto &SrcMgr = DiagInfo->SrcMgr; 571*09467b48Spatrick SMLoc Loc = SMLoc::getFromPointer( 572*09467b48Spatrick SrcMgr.getMemoryBuffer(BufNum)->getBuffer().begin()); 573*09467b48Spatrick 574*09467b48Spatrick std::string Msg = "inline asm clobber list contains reserved registers: "; 575*09467b48Spatrick for (auto I = RestrRegs.begin(), E = RestrRegs.end(); I != E; I++) { 576*09467b48Spatrick if(I != RestrRegs.begin()) 577*09467b48Spatrick Msg += ", "; 578*09467b48Spatrick Msg += *I; 579*09467b48Spatrick } 580*09467b48Spatrick std::string Note = "Reserved registers on the clobber list may not be " 581*09467b48Spatrick "preserved across the asm statement, and clobbering them may " 582*09467b48Spatrick "lead to undefined behaviour."; 583*09467b48Spatrick SrcMgr.PrintMessage(Loc, SourceMgr::DK_Warning, Msg); 584*09467b48Spatrick SrcMgr.PrintMessage(Loc, SourceMgr::DK_Note, Note); 585*09467b48Spatrick } 586*09467b48Spatrick 587*09467b48Spatrick EmitInlineAsm(OS.str(), getSubtargetInfo(), TM.Options.MCOptions, LocMD, 588*09467b48Spatrick MI->getInlineAsmDialect()); 589*09467b48Spatrick 590*09467b48Spatrick // Emit the #NOAPP end marker. This has to happen even if verbose-asm isn't 591*09467b48Spatrick // enabled, so we use emitRawComment. 592*09467b48Spatrick OutStreamer->emitRawComment(MAI->getInlineAsmEnd()); 593*09467b48Spatrick } 594*09467b48Spatrick 595*09467b48Spatrick 596*09467b48Spatrick /// PrintSpecial - Print information related to the specified machine instr 597*09467b48Spatrick /// that is independent of the operand, and may be independent of the instr 598*09467b48Spatrick /// itself. This can be useful for portably encoding the comment character 599*09467b48Spatrick /// or other bits of target-specific knowledge into the asmstrings. The 600*09467b48Spatrick /// syntax used is ${:comment}. Targets can override this to add support 601*09467b48Spatrick /// for their own strange codes. 602*09467b48Spatrick void AsmPrinter::PrintSpecial(const MachineInstr *MI, raw_ostream &OS, 603*09467b48Spatrick const char *Code) const { 604*09467b48Spatrick if (!strcmp(Code, "private")) { 605*09467b48Spatrick const DataLayout &DL = MF->getDataLayout(); 606*09467b48Spatrick OS << DL.getPrivateGlobalPrefix(); 607*09467b48Spatrick } else if (!strcmp(Code, "comment")) { 608*09467b48Spatrick OS << MAI->getCommentString(); 609*09467b48Spatrick } else if (!strcmp(Code, "uid")) { 610*09467b48Spatrick // Comparing the address of MI isn't sufficient, because machineinstrs may 611*09467b48Spatrick // be allocated to the same address across functions. 612*09467b48Spatrick 613*09467b48Spatrick // If this is a new LastFn instruction, bump the counter. 614*09467b48Spatrick if (LastMI != MI || LastFn != getFunctionNumber()) { 615*09467b48Spatrick ++Counter; 616*09467b48Spatrick LastMI = MI; 617*09467b48Spatrick LastFn = getFunctionNumber(); 618*09467b48Spatrick } 619*09467b48Spatrick OS << Counter; 620*09467b48Spatrick } else { 621*09467b48Spatrick std::string msg; 622*09467b48Spatrick raw_string_ostream Msg(msg); 623*09467b48Spatrick Msg << "Unknown special formatter '" << Code 624*09467b48Spatrick << "' for machine instr: " << *MI; 625*09467b48Spatrick report_fatal_error(Msg.str()); 626*09467b48Spatrick } 627*09467b48Spatrick } 628*09467b48Spatrick 629*09467b48Spatrick void AsmPrinter::PrintSymbolOperand(const MachineOperand &MO, raw_ostream &OS) { 630*09467b48Spatrick assert(MO.isGlobal() && "caller should check MO.isGlobal"); 631*09467b48Spatrick getSymbol(MO.getGlobal())->print(OS, MAI); 632*09467b48Spatrick printOffset(MO.getOffset(), OS); 633*09467b48Spatrick } 634*09467b48Spatrick 635*09467b48Spatrick /// PrintAsmOperand - Print the specified operand of MI, an INLINEASM 636*09467b48Spatrick /// instruction, using the specified assembler variant. Targets should 637*09467b48Spatrick /// override this to format as appropriate for machine specific ExtraCodes 638*09467b48Spatrick /// or when the arch-independent handling would be too complex otherwise. 639*09467b48Spatrick bool AsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, 640*09467b48Spatrick const char *ExtraCode, raw_ostream &O) { 641*09467b48Spatrick // Does this asm operand have a single letter operand modifier? 642*09467b48Spatrick if (ExtraCode && ExtraCode[0]) { 643*09467b48Spatrick if (ExtraCode[1] != 0) return true; // Unknown modifier. 644*09467b48Spatrick 645*09467b48Spatrick // https://gcc.gnu.org/onlinedocs/gccint/Output-Template.html 646*09467b48Spatrick const MachineOperand &MO = MI->getOperand(OpNo); 647*09467b48Spatrick switch (ExtraCode[0]) { 648*09467b48Spatrick default: 649*09467b48Spatrick return true; // Unknown modifier. 650*09467b48Spatrick case 'a': // Print as memory address. 651*09467b48Spatrick if (MO.isReg()) { 652*09467b48Spatrick PrintAsmMemoryOperand(MI, OpNo, nullptr, O); 653*09467b48Spatrick return false; 654*09467b48Spatrick } 655*09467b48Spatrick LLVM_FALLTHROUGH; // GCC allows '%a' to behave like '%c' with immediates. 656*09467b48Spatrick case 'c': // Substitute immediate value without immediate syntax 657*09467b48Spatrick if (MO.isImm()) { 658*09467b48Spatrick O << MO.getImm(); 659*09467b48Spatrick return false; 660*09467b48Spatrick } 661*09467b48Spatrick if (MO.isGlobal()) { 662*09467b48Spatrick PrintSymbolOperand(MO, O); 663*09467b48Spatrick return false; 664*09467b48Spatrick } 665*09467b48Spatrick return true; 666*09467b48Spatrick case 'n': // Negate the immediate constant. 667*09467b48Spatrick if (!MO.isImm()) 668*09467b48Spatrick return true; 669*09467b48Spatrick O << -MO.getImm(); 670*09467b48Spatrick return false; 671*09467b48Spatrick case 's': // The GCC deprecated s modifier 672*09467b48Spatrick if (!MO.isImm()) 673*09467b48Spatrick return true; 674*09467b48Spatrick O << ((32 - MO.getImm()) & 31); 675*09467b48Spatrick return false; 676*09467b48Spatrick } 677*09467b48Spatrick } 678*09467b48Spatrick return true; 679*09467b48Spatrick } 680*09467b48Spatrick 681*09467b48Spatrick bool AsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, 682*09467b48Spatrick const char *ExtraCode, raw_ostream &O) { 683*09467b48Spatrick // Target doesn't support this yet! 684*09467b48Spatrick return true; 685*09467b48Spatrick } 686*09467b48Spatrick 687*09467b48Spatrick void AsmPrinter::emitInlineAsmStart() const {} 688*09467b48Spatrick 689*09467b48Spatrick void AsmPrinter::emitInlineAsmEnd(const MCSubtargetInfo &StartInfo, 690*09467b48Spatrick const MCSubtargetInfo *EndInfo) const {} 691