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

1

2

3

4

5

6

7

8

9

10

11

12

41using namespace llvm;

42

43#define DEBUG_TYPE "asm-printer"

44

45unsigned AsmPrinter::addInlineAsmDiagBuffer(StringRef AsmStr,

46 const MDNode *LocMDNode) const {

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

51

52 std::unique_ptr Buffer;

53

54

56

57

59

60

61 if (LocMDNode) {

62 LocInfos.resize(BufNum);

63 LocInfos[BufNum - 1] = LocMDNode;

64 }

65

66 return BufNum;

67}

68

69

70

73 const MDNode *LocMDNode,

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

76

77

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

79 if (isNullTerminated)

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

81

82

83

84

85

86

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

91 OutStreamer->isIntegratedAssemblerRequired()) {

95 return;

96 }

97

98 unsigned BufNum = addInlineAsmDiagBuffer(Str, LocMDNode);

101

102 std::unique_ptr Parser(

104

105

106

107

108

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

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

113 if (!TAP)

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

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

116

117

119 Parser->setAssemblerDialect(Dialect);

120

121

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

124 }

125 Parser->setTargetParser(*TAP);

126

128

129 (void)Parser->Run( true,

130 true);

132}

133

139

140 if (InputIsIntelDialect) {

141

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

143 }

144

145 int CurVariant = -1;

146 const char *LastEmitted = AsmStr;

147 unsigned NumOperands = MI->getNumOperands();

148

149 int AsmPrinterVariant;

150 if (InputIsIntelDialect)

151 AsmPrinterVariant = 1;

152 else

154

155

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

157 OS << '\t';

158

159 while (*LastEmitted) {

160 switch (*LastEmitted) {

161 default: {

162

163 const char *LiteralEnd = LastEmitted+1;

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

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

166 ++LiteralEnd;

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

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

169 LastEmitted = LiteralEnd;

170 break;

171 }

172 case '\n':

173 ++LastEmitted;

174 OS << '\n';

175 break;

176 case '$': {

177 ++LastEmitted;

178 bool Done = true;

179

180

181 switch (*LastEmitted) {

182 default: Done = false; break;

183 case '$':

184 if (!InputIsIntelDialect)

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

186 OS << '$';

187 ++LastEmitted;

188 break;

189 case '(':

190 ++LastEmitted;

191 if (CurVariant != -1)

193 Twine(AsmStr) + "'");

194 CurVariant = 0;

195 break;

196 case '|':

197 ++LastEmitted;

198 if (CurVariant == -1)

199 OS << '|';

200 else

201 ++CurVariant;

202 break;

203 case ')':

204 ++LastEmitted;

205 if (CurVariant == -1)

206 OS << '}';

207 else

208 CurVariant = -1;

209 break;

210 }

211 if (Done) break;

212

213 bool HasCurlyBraces = false;

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

215 ++LastEmitted;

216 HasCurlyBraces = true;

217 }

218

219

220

221

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

223 ++LastEmitted;

224 const char *StrStart = LastEmitted;

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

226 if (!StrEnd)

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

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

231 LastEmitted = StrEnd+1;

232 break;

233 }

234

235 const char *IDStart = LastEmitted;

236 const char *IDEnd = IDStart;

238 ++IDEnd;

239

240 unsigned Val;

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

243 Twine(AsmStr) + "'");

244 LastEmitted = IDEnd;

245

246 if (Val >= NumOperands - 1)

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

248 Twine(AsmStr) + "'");

249

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

251

252 if (HasCurlyBraces) {

253

254

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

256 ++LastEmitted;

257 if (*LastEmitted == 0)

259 Twine(AsmStr) + "'");

260

261 Modifier[0] = *LastEmitted;

262 ++LastEmitted;

263 }

264

265 if (*LastEmitted != '}')

267 Twine(AsmStr) + "'");

268 ++LastEmitted;

269 }

270

271

272

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

275

276 bool Error = false;

277

278

279 for (; Val; --Val) {

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

281 break;

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

284 }

285

286

287

288

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

291 } else {

293 ++OpNo;

294

295

296

297

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

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

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

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

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

309 } else {

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

312 }

313 }

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

317 LocCookie,

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

319 }

320 }

321 break;

322 }

323 }

324 }

325 if (InputIsIntelDialect)

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

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

328}

329

330

331

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

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

334

335

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

337

338

339

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

343 return;

344 }

345

346

347

349

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

352 LocMD

353 ? mdconst::extract(LocMD->getOperand(0))->getZExtValue()

354 : 0;

355

356

357

360

363

364

365

368

370 I < NumOps; ++I) {

373 continue;

375 if (F.isClobberKind()) {

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

379 }

380

381 I += F.getNumOperandRegisters();

382 }

383

384 if (!RestrRegs.empty()) {

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

386 ListSeparator LS;

387 for (const Register RR : RestrRegs) {

388 Msg += LS;

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

390 }

391

393 const char *Note =

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

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

396 "lead to undefined behaviour.";

402

403 for (const Register RR : RestrRegs) {

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

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

408 }

409 }

410 }

411

413 MI->getInlineAsmDialect());

414

415

416

418}

419

420

421

422

423

424

425

428 if (Code == "private") {

430 OS << DL.getPrivateGlobalPrefix();

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

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

434

435

436

437

439 ++Counter;

440 LastMI = MI;

442 }

443 OS << Counter;

444 } else {

445 std::string msg;

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

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

450 }

451}

452

454 assert(MO.isGlobal() && "caller should check MO.isGlobal");

457}

458

459

460

461

462

465

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

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

468

469

471 switch (ExtraCode[0]) {

472 default:

473 return true;

474 case 'a':

475 if (MO.isReg()) {

477 return false;

478 }

479 [[fallthrough]];

480 case 'c':

481 if (MO.isImm()) {

483 return false;

484 }

487 return false;

488 }

489 return true;

490 case 'n':

492 return true;

494 return false;

495 case 's':

497 return true;

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

499 return false;

500 }

501 }

502 return true;

503}

504

507

508 return true;

509}

510

512

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.

unsigned const TargetRegisterInfo * TRI

static bool isDigit(const char C)

assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())

This file defines the SmallString class.

This file defines the SmallVector class.

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.

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.

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.

This is an important class for using LLVM in a threaded context.

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

const char * getInlineAsmStart() const

bool useIntegratedAssembler() const

Return true if assembly (inline or otherwise) should be parsed.

const char * getInlineAsmEnd() const

StringRef getCommentString() const

bool parseInlineAsmUsingAsmParser() const

Return true if target want to use AsmParser to parse inlineasm.

Context object for machine code objects.

void registerInlineAsmLabel(MCSymbol *Sym)

registerInlineAsmLabel - Records that the name is a label referenced in inline assembly.

void initInlineSourceManager()

SourceMgr * getInlineSourceManager()

std::vector< const MDNode * > & getLocInfos()

Generic base class for all target subtargets.

MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...

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

MCSymbol * getSymbol() const

Return the MCSymbol for this basic block.

const TargetSubtargetInfo & getSubtarget() const

getSubtarget - Return the subtarget for which this machine code is being compiled.

const DataLayout & getDataLayout() const

Return the DataLayout attached to the Module associated to this MF.

Function & getFunction()

Return the LLVM function that this machine code represents.

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.

Wrapper class representing virtual and physical registers.

Represents a location in source code.

SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...

void push_back(const T &Elt)

This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.

This owns the files read by a parser, handles include stacks, and handles diagnostic wrangling.

void setIncludeDirs(const std::vector< std::string > &Dirs)

unsigned AddNewSourceBuffer(std::unique_ptr< MemoryBuffer > F, SMLoc IncludeLoc)

Add a new source buffer to this source manager.

StringRef - Represent a constant reference to a string, i.e.

const Triple & getTargetTriple() const

virtual int unqualifiedInlineAsmVariant() const

The default variant to use in unqualified asm instructions.

const Target & getTarget() const

const MCAsmInfo * getMCAsmInfo() const

Return target specific asm information.

MCTargetOptions MCOptions

Machine level options.

TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...

virtual const TargetRegisterInfo * getRegisterInfo() const

getRegisterInfo - If register information is available, return it.

MCTargetAsmParser * createMCAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser, const MCInstrInfo &MII, const MCTargetOptions &Options) const

createMCAsmParser - Create a target specific assembly parser.

MCInstrInfo * createMCInstrInfo() const

createMCInstrInfo - Create a MCInstrInfo implementation.

bool isX86() const

Tests whether the target is x86 (32- or 64-bit).

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.

A raw_ostream that writes to an SmallVector or SmallString.

Reg

All possible values of the reg field in the ModR/M byte.

This is an optimization pass for GlobalISel generic memory operations.

void report_fatal_error(Error Err, bool gen_crash_diag=true)

Report a serious error, calling any installed error handler.

MCAsmParser * createMCAsmParser(SourceMgr &, MCContext &, MCStreamer &, const MCAsmInfo &, unsigned CB=0)

Create an MCAsmParser instance for parsing assembly similar to gas syntax.