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

1

2

3

4

5

6

7

8

9

10

11

12

42using namespace llvm;

43

44#define DEBUG_TYPE "asm-printer"

45

46unsigned AsmPrinter::addInlineAsmDiagBuffer(StringRef AsmStr,

47 const MDNode *LocMDNode) const {

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

52

53 std::unique_ptr Buffer;

54

55

57

58

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

60

61

62 if (LocMDNode) {

63 LocInfos.resize(BufNum);

64 LocInfos[BufNum - 1] = LocMDNode;

65 }

66

67 return BufNum;

68}

69

70

71

74 const MDNode *LocMDNode,

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

77

78

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

80 if (isNullTerminated)

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

82

83

84

85

86

87

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

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

92 OutStreamer->isIntegratedAssemblerRequired()) {

96 return;

97 }

98

99 unsigned BufNum = addInlineAsmDiagBuffer(Str, LocMDNode);

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

103

104 std::unique_ptr Parser(

106

107

108

109

110

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

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

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

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

115 if (!TAP)

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

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

118

119

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

121 Parser->setAssemblerDialect(Dialect);

122

123

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

126 }

127 Parser->setTargetParser(*TAP);

128

130

131 (void)Parser->Run( true,

132 true);

134}

135

141

142 if (InputIsIntelDialect) {

143

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

145 }

146

147 int CurVariant = -1;

148 const char *LastEmitted = AsmStr;

149 unsigned NumOperands = MI->getNumOperands();

150

151 int AsmPrinterVariant;

152 if (InputIsIntelDialect)

153 AsmPrinterVariant = 1;

154 else

156

157

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

159 OS << '\t';

160

161 while (*LastEmitted) {

162 switch (*LastEmitted) {

163 default: {

164

165 const char *LiteralEnd = LastEmitted+1;

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

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

168 ++LiteralEnd;

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

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

171 LastEmitted = LiteralEnd;

172 break;

173 }

174 case '\n':

175 ++LastEmitted;

176 OS << '\n';

177 break;

178 case '$': {

179 ++LastEmitted;

180 bool Done = true;

181

182

183 switch (*LastEmitted) {

184 default: Done = false; break;

185 case '$':

186 if (!InputIsIntelDialect)

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

188 OS << '$';

189 ++LastEmitted;

190 break;

191 case '(':

192 ++LastEmitted;

193 if (CurVariant != -1)

195 Twine(AsmStr) + "'");

196 CurVariant = 0;

197 break;

198 case '|':

199 ++LastEmitted;

200 if (CurVariant == -1)

201 OS << '|';

202 else

203 ++CurVariant;

204 break;

205 case ')':

206 ++LastEmitted;

207 if (CurVariant == -1)

208 OS << '}';

209 else

210 CurVariant = -1;

211 break;

212 }

213 if (Done) break;

214

215 bool HasCurlyBraces = false;

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

217 ++LastEmitted;

218 HasCurlyBraces = true;

219 }

220

221

222

223

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

225 ++LastEmitted;

226 const char *StrStart = LastEmitted;

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

228 if (!StrEnd)

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

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

233 LastEmitted = StrEnd+1;

234 break;

235 }

236

237 const char *IDStart = LastEmitted;

238 const char *IDEnd = IDStart;

240 ++IDEnd;

241

242 unsigned Val;

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

245 Twine(AsmStr) + "'");

246 LastEmitted = IDEnd;

247

248 if (Val >= NumOperands - 1)

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

250 Twine(AsmStr) + "'");

251

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

253

254 if (HasCurlyBraces) {

255

256

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

258 ++LastEmitted;

259 if (*LastEmitted == 0)

261 Twine(AsmStr) + "'");

262

263 Modifier[0] = *LastEmitted;

264 ++LastEmitted;

265 }

266

267 if (*LastEmitted != '}')

269 Twine(AsmStr) + "'");

270 ++LastEmitted;

271 }

272

273

274

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

277

278 bool Error = false;

279

280

281 for (; Val; --Val) {

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

283 break;

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

286 }

287

288

289

290

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

293 } else {

295 ++OpNo;

296

297

298

299

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

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

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

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

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

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

311 } else {

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

314 }

315 }

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

319 LocCookie,

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

321 }

322 }

323 break;

324 }

325 }

326 }

327 if (InputIsIntelDialect)

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

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

330}

331

332

333

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

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

336

337

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

339

340

341

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

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

345 return;

346 }

347

348

349

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

351

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

353 uint64_t LocCookie =

354 LocMD

356 : 0;

357

358

359

360 SmallString<256> StringData;

361 raw_svector_ostream OS(StringData);

362

365

366

367

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

370

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

375 continue;

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

377 if (F.isClobberKind()) {

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

381 }

382

383 I += F.getNumOperandRegisters();

384 }

385

386 if (!RestrRegs.empty()) {

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

388 ListSeparator LS;

389 for (const Register RR : RestrRegs) {

390 Msg += LS;

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

392 }

393

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

395 const char *Note =

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

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

398 "lead to undefined behaviour.";

400 Ctx.diagnose(DiagnosticInfoInlineAsm(LocCookie, Msg,

404

405 for (const Register RR : RestrRegs) {

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

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

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

410 }

411 }

412 }

413

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

415 MI->getInlineAsmDialect());

416

417

418

420}

421

422

423

424

425

426

427

430 if (Code == "private") {

432 OS << DL.getPrivateGlobalPrefix();

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

434 OS << MAI->getCommentString();

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

436

437

438

439

441 ++Counter;

442 LastMI = MI;

444 }

445 OS << Counter;

446 } else {

447 std::string msg;

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

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

452 }

453}

454

460

461

462

463

464

467

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

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

470

471

473 switch (ExtraCode[0]) {

474 default:

475 return true;

476 case 'a':

477 if (MO.isReg()) {

479 return false;

480 }

481 [[fallthrough]];

482 case 'c':

483 if (MO.isImm()) {

485 return false;

486 }

489 return false;

490 }

491 return true;

492 case 'n':

494 return true;

496 return false;

497 case 's':

499 return true;

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

501 return false;

502 }

503 }

504 return true;

505}

506

509

510 return true;

511}

512

514

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:136

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:515

IntrusiveRefCntPtr< vfs::FileSystem > VFS

The VFS to resolve asm include directives.

TargetMachine & TM

Target machine description.

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

Print the MachineOperand as a symbol.

Definition AsmPrinterInlineAsm.cpp:455

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:428

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:507

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:513

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:465

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.

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.