LLVM: lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

43using namespace llvm;

44

45#define DEBUG_TYPE "asm-printer"

46

47unsigned AsmPrinter::addInlineAsmDiagBuffer(StringRef AsmStr,

48 const MDNode *LocMDNode) const {

52 std::vector<const MDNode *> &LocInfos = Context.getLocInfos();

53

54 std::unique_ptr Buffer;

55

56

58

59

60 unsigned BufNum = SrcMgr.AddNewSourceBuffer(std::move(Buffer), SMLoc());

61

62

63 if (LocMDNode) {

64 LocInfos.resize(BufNum);

65 LocInfos[BufNum - 1] = LocMDNode;

66 }

67

68 return BufNum;

69}

70

71

72

75 const MDNode *LocMDNode,

77 assert(!Str.empty() && "Can't emit empty inline asm block");

78

79

80 bool isNullTerminated = Str.back() == 0;

81 if (isNullTerminated)

82 Str = Str.substr(0, Str.size()-1);

83

84

85

86

87

88

89 const MCAsmInfo *MCAI = TM.getMCAsmInfo();

90 assert(MCAI && "No MCAsmInfo");

93 OutStreamer->isIntegratedAssemblerRequired()) {

97 return;

98 }

99

100 unsigned BufNum = addInlineAsmDiagBuffer(Str, LocMDNode);

101 SourceMgr &SrcMgr = *MMI->getContext().getInlineSourceManager();

104

107 }());

108

109 std::unique_ptr Parser(

111

112

113

114

115

116 std::unique_ptr MII(TM.getTarget().createMCInstrInfo());

117 assert(MII && "Failed to create instruction info");

118 std::unique_ptr TAP(TM.getTarget().createMCAsmParser(

119 STI, *Parser, *MII, MCOptions));

120 if (!TAP)

121 report_fatal_error("Inline asm not supported by this streamer because"

122 " we don't have an asm parser for this target\n");

123

124

125 if (TM.getTargetTriple().isX86()) {

126 Parser->setAssemblerDialect(Dialect);

127

128

130 Parser->getLexer().setLexMasmIntegers(true);

131 }

132 Parser->setTargetParser(*TAP);

133

135

136 (void)Parser->Run( true,

137 true);

139}

140

146

147 if (InputIsIntelDialect) {

148

149 OS << "\t.intel_syntax\n\t";

150 }

151

152 int CurVariant = -1;

153 const char *LastEmitted = AsmStr;

154 unsigned NumOperands = MI->getNumOperands();

155

156 int AsmPrinterVariant;

157 if (InputIsIntelDialect)

158 AsmPrinterVariant = 1;

159 else

161

162

163 if (!InputIsIntelDialect && !MAI->isHLASM())

164 OS << '\t';

165

166 while (*LastEmitted) {

167 switch (*LastEmitted) {

168 default: {

169

170 const char *LiteralEnd = LastEmitted+1;

171 while (*LiteralEnd && *LiteralEnd != '{' && *LiteralEnd != '|' &&

172 *LiteralEnd != '}' && *LiteralEnd != '$' && *LiteralEnd != '\n')

173 ++LiteralEnd;

174 if (CurVariant == -1 || CurVariant == AsmPrinterVariant)

175 OS.write(LastEmitted, LiteralEnd - LastEmitted);

176 LastEmitted = LiteralEnd;

177 break;

178 }

179 case '\n':

180 ++LastEmitted;

181 OS << '\n';

182 break;

183 case '$': {

184 ++LastEmitted;

185 bool Done = true;

186

187

188 switch (*LastEmitted) {

189 default: Done = false; break;

190 case '$':

191 if (!InputIsIntelDialect)

192 if (CurVariant == -1 || CurVariant == AsmPrinterVariant)

193 OS << '$';

194 ++LastEmitted;

195 break;

196 case '(':

197 ++LastEmitted;

198 if (CurVariant != -1)

200 Twine(AsmStr) + "'");

201 CurVariant = 0;

202 break;

203 case '|':

204 ++LastEmitted;

205 if (CurVariant == -1)

206 OS << '|';

207 else

208 ++CurVariant;

209 break;

210 case ')':

211 ++LastEmitted;

212 if (CurVariant == -1)

213 OS << '}';

214 else

215 CurVariant = -1;

216 break;

217 }

218 if (Done) break;

219

220 bool HasCurlyBraces = false;

221 if (*LastEmitted == '{') {

222 ++LastEmitted;

223 HasCurlyBraces = true;

224 }

225

226

227

228

229 if (HasCurlyBraces && *LastEmitted == ':') {

230 ++LastEmitted;

231 const char *StrStart = LastEmitted;

232 const char *StrEnd = strchr(StrStart, '}');

233 if (!StrEnd)

235 " string: '" + Twine(AsmStr) + "'");

236 if (CurVariant == -1 || CurVariant == AsmPrinterVariant)

238 LastEmitted = StrEnd+1;

239 break;

240 }

241

242 const char *IDStart = LastEmitted;

243 const char *IDEnd = IDStart;

245 ++IDEnd;

246

247 unsigned Val;

248 if (StringRef(IDStart, IDEnd-IDStart).getAsInteger(10, Val))

250 Twine(AsmStr) + "'");

251 LastEmitted = IDEnd;

252

253 if (Val >= NumOperands - 1)

254 report_fatal_error("Invalid $ operand number in inline asm string: '" +

255 Twine(AsmStr) + "'");

256

257 char Modifier[2] = { 0, 0 };

258

259 if (HasCurlyBraces) {

260

261

262 if (*LastEmitted == ':') {

263 ++LastEmitted;

264 if (*LastEmitted == 0)

266 Twine(AsmStr) + "'");

267

268 Modifier[0] = *LastEmitted;

269 ++LastEmitted;

270 }

271

272 if (*LastEmitted != '}')

274 Twine(AsmStr) + "'");

275 ++LastEmitted;

276 }

277

278

279

280 if (CurVariant == -1 || CurVariant == AsmPrinterVariant) {

282

283 bool Error = false;

284

285

286 for (; Val; --Val) {

287 if (OpNo >= MI->getNumOperands())

288 break;

290 OpNo += F.getNumOperandRegisters() + 1;

291 }

292

293

294

295

296 if (OpNo >= MI->getNumOperands() || MI->getOperand(OpNo).isMetadata()) {

298 } else {

300 ++OpNo;

301

302

303

304

305 if (MI->getOperand(OpNo).isBlockAddress()) {

306 const BlockAddress *BA = MI->getOperand(OpNo).getBlockAddress();

310 } else if (MI->getOperand(OpNo).isMBB()) {

311 const MCSymbol *Sym = MI->getOperand(OpNo).getMBB()->getSymbol();

313 } else if (F.isMemKind()) {

315 MI, OpNo, Modifier[0] ? Modifier : nullptr, OS);

316 } else {

318 Modifier[0] ? Modifier : nullptr, OS);

319 }

320 }

322 const Function &Fn = MI->getMF()->getFunction();

324 LocCookie,

325 "invalid operand in inline asm: '" + Twine(AsmStr) + "'"));

326 }

327 }

328 break;

329 }

330 }

331 }

332 if (InputIsIntelDialect)

333 OS << "\n\t.att_syntax";

334 OS << '\n' << (char)0;

335}

336

337

338

339void AsmPrinter::emitInlineAsm(const MachineInstr *MI) const {

340 assert(MI->isInlineAsm() && "printInlineAsm only works on inline asms");

341

342

343 const char *AsmStr = MI->getOperand(0).getSymbolName();

344

345

346

347 if (AsmStr[0] == 0) {

348 OutStreamer->emitRawComment(MAI->getInlineAsmStart());

350 return;

351 }

352

353

354

355 OutStreamer->emitRawComment(MAI->getInlineAsmStart());

356

357 const MDNode *LocMD = MI->getLocCookieMD();

358 uint64_t LocCookie =

359 LocMD

361 : 0;

362

363

364

365 SmallString<256> StringData;

366 raw_svector_ostream OS(StringData);

367

370

371

372

374 const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo();

375

378 const MachineOperand &MO = MI->getOperand(I);

380 continue;

381 const InlineAsm::Flag F(MO.getImm());

382 if (F.isClobberKind()) {

384 if (TRI->isAsmClobberable(*MF, Reg))

386 }

387

388 I += F.getNumOperandRegisters();

389 }

390

391 if (!RestrRegs.empty()) {

392 std::string Msg = "inline asm clobber list contains reserved registers: ";

393 ListSeparator LS;

394 for (const Register RR : RestrRegs) {

395 Msg += LS;

396 Msg += TRI->getRegAsmName(RR);

397 }

398

399 const Function &Fn = MF->getFunction();

400 const char *Note =

401 "Reserved registers on the clobber list may not be "

402 "preserved across the asm statement, and clobbering them may "

403 "lead to undefined behaviour.";

405 Ctx.diagnose(DiagnosticInfoInlineAsm(LocCookie, Msg,

409

410 for (const Register RR : RestrRegs) {

411 if (std::optionalstd::string reason =

412 TRI->explainReservedReg(*MF, RR)) {

413 Ctx.diagnose(DiagnosticInfoInlineAsm(LocCookie, *reason,

415 }

416 }

417 }

418

419 emitInlineAsm(StringData, getSubtargetInfo(), TM.Options.MCOptions, LocMD,

420 MI->getInlineAsmDialect());

421

422

423

425}

426

427

428

429

430

431

432

435 if (Code == "private") {

437 OS << DL.getPrivateGlobalPrefix();

438 } else if (Code == "comment") {

439 OS << MAI->getCommentString();

440 } else if (Code == "uid") {

441

442

443

444

446 ++Counter;

447 LastMI = MI;

449 }

450 OS << Counter;

451 } else {

452 std::string msg;

454 Msg << "Unknown special formatter '" << Code

455 << "' for machine instr: " << *MI;

457 }

458}

459

465

466

467

468

469

472

473 if (ExtraCode && ExtraCode[0]) {

474 if (ExtraCode[1] != 0) return true;

475

476

478 switch (ExtraCode[0]) {

479 default:

480 return true;

481 case 'a':

482 if (MO.isReg()) {

484 return false;

485 }

486 [[fallthrough]];

487 case 'c':

488 if (MO.isImm()) {

490 return false;

491 }

494 return false;

495 }

496 return true;

497 case 'n':

499 return true;

501 return false;

502 case 's':

504 return true;

505 O << ((32 - MO.getImm()) & 31);

506 return false;

507 }

508 }

509 return true;

510}

511

514

515 return true;

516}

517

519

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)

Definition AsmPrinterInlineAsm.cpp:141

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

Let the target do anything it needs to do after emitting inlineasm.

Definition AsmPrinterInlineAsm.cpp:520

TargetMachine & TM

Target machine description.

virtual void PrintSymbolOperand(const MachineOperand &MO, raw_ostream &OS)

Print the MachineOperand as a symbol.

Definition AsmPrinterInlineAsm.cpp:460

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,...

Definition AsmPrinterInlineAsm.cpp:433

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...

Definition AsmPrinterInlineAsm.cpp:512

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.

Definition AsmPrinterInlineAsm.cpp:518

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.

Definition AsmPrinterInlineAsm.cpp:470

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.