Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/Target/SPIRV/SPIRVAsmPrinter.cpp
35266 views
1
//===-- SPIRVAsmPrinter.cpp - SPIR-V LLVM assembly writer ------*- C++ -*--===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
//
9
// This file contains a printer that converts from our internal representation
10
// of machine-dependent LLVM code to the SPIR-V assembly language.
11
//
12
//===----------------------------------------------------------------------===//
13
14
#include "MCTargetDesc/SPIRVInstPrinter.h"
15
#include "SPIRV.h"
16
#include "SPIRVInstrInfo.h"
17
#include "SPIRVMCInstLower.h"
18
#include "SPIRVModuleAnalysis.h"
19
#include "SPIRVSubtarget.h"
20
#include "SPIRVTargetMachine.h"
21
#include "SPIRVUtils.h"
22
#include "TargetInfo/SPIRVTargetInfo.h"
23
#include "llvm/ADT/DenseMap.h"
24
#include "llvm/Analysis/ValueTracking.h"
25
#include "llvm/CodeGen/AsmPrinter.h"
26
#include "llvm/CodeGen/MachineConstantPool.h"
27
#include "llvm/CodeGen/MachineFunctionPass.h"
28
#include "llvm/CodeGen/MachineInstr.h"
29
#include "llvm/CodeGen/MachineModuleInfo.h"
30
#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
31
#include "llvm/MC/MCAsmInfo.h"
32
#include "llvm/MC/MCAssembler.h"
33
#include "llvm/MC/MCInst.h"
34
#include "llvm/MC/MCObjectStreamer.h"
35
#include "llvm/MC/MCSPIRVObjectWriter.h"
36
#include "llvm/MC/MCStreamer.h"
37
#include "llvm/MC/MCSymbol.h"
38
#include "llvm/MC/TargetRegistry.h"
39
#include "llvm/Support/raw_ostream.h"
40
41
using namespace llvm;
42
43
#define DEBUG_TYPE "asm-printer"
44
45
namespace {
46
class SPIRVAsmPrinter : public AsmPrinter {
47
unsigned NLabels = 0;
48
49
public:
50
explicit SPIRVAsmPrinter(TargetMachine &TM,
51
std::unique_ptr<MCStreamer> Streamer)
52
: AsmPrinter(TM, std::move(Streamer)), ST(nullptr), TII(nullptr) {}
53
bool ModuleSectionsEmitted;
54
const SPIRVSubtarget *ST;
55
const SPIRVInstrInfo *TII;
56
57
StringRef getPassName() const override { return "SPIRV Assembly Printer"; }
58
void printOperand(const MachineInstr *MI, int OpNum, raw_ostream &O);
59
bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
60
const char *ExtraCode, raw_ostream &O) override;
61
62
void outputMCInst(MCInst &Inst);
63
void outputInstruction(const MachineInstr *MI);
64
void outputModuleSection(SPIRV::ModuleSectionType MSType);
65
void outputGlobalRequirements();
66
void outputEntryPoints();
67
void outputDebugSourceAndStrings(const Module &M);
68
void outputOpExtInstImports(const Module &M);
69
void outputOpMemoryModel();
70
void outputOpFunctionEnd();
71
void outputExtFuncDecls();
72
void outputExecutionModeFromMDNode(Register Reg, MDNode *Node,
73
SPIRV::ExecutionMode::ExecutionMode EM,
74
unsigned ExpectMDOps, int64_t DefVal);
75
void outputExecutionModeFromNumthreadsAttribute(
76
const Register &Reg, const Attribute &Attr,
77
SPIRV::ExecutionMode::ExecutionMode EM);
78
void outputExecutionMode(const Module &M);
79
void outputAnnotations(const Module &M);
80
void outputModuleSections();
81
82
void emitInstruction(const MachineInstr *MI) override;
83
void emitFunctionEntryLabel() override {}
84
void emitFunctionHeader() override;
85
void emitFunctionBodyStart() override {}
86
void emitFunctionBodyEnd() override;
87
void emitBasicBlockStart(const MachineBasicBlock &MBB) override;
88
void emitBasicBlockEnd(const MachineBasicBlock &MBB) override {}
89
void emitGlobalVariable(const GlobalVariable *GV) override {}
90
void emitOpLabel(const MachineBasicBlock &MBB);
91
void emitEndOfAsmFile(Module &M) override;
92
bool doInitialization(Module &M) override;
93
94
void getAnalysisUsage(AnalysisUsage &AU) const override;
95
SPIRV::ModuleAnalysisInfo *MAI;
96
};
97
} // namespace
98
99
void SPIRVAsmPrinter::getAnalysisUsage(AnalysisUsage &AU) const {
100
AU.addRequired<SPIRVModuleAnalysis>();
101
AU.addPreserved<SPIRVModuleAnalysis>();
102
AsmPrinter::getAnalysisUsage(AU);
103
}
104
105
// If the module has no functions, we need output global info anyway.
106
void SPIRVAsmPrinter::emitEndOfAsmFile(Module &M) {
107
if (ModuleSectionsEmitted == false) {
108
outputModuleSections();
109
ModuleSectionsEmitted = true;
110
}
111
112
ST = static_cast<const SPIRVTargetMachine &>(TM).getSubtargetImpl();
113
VersionTuple SPIRVVersion = ST->getSPIRVVersion();
114
uint32_t Major = SPIRVVersion.getMajor();
115
uint32_t Minor = SPIRVVersion.getMinor().value_or(0);
116
// Bound is an approximation that accounts for the maximum used register
117
// number and number of generated OpLabels
118
unsigned Bound = 2 * (ST->getBound() + 1) + NLabels;
119
if (MCAssembler *Asm = OutStreamer->getAssemblerPtr())
120
static_cast<SPIRVObjectWriter &>(Asm->getWriter())
121
.setBuildVersion(Major, Minor, Bound);
122
}
123
124
void SPIRVAsmPrinter::emitFunctionHeader() {
125
if (ModuleSectionsEmitted == false) {
126
outputModuleSections();
127
ModuleSectionsEmitted = true;
128
}
129
// Get the subtarget from the current MachineFunction.
130
ST = &MF->getSubtarget<SPIRVSubtarget>();
131
TII = ST->getInstrInfo();
132
const Function &F = MF->getFunction();
133
134
if (isVerbose()) {
135
OutStreamer->getCommentOS()
136
<< "-- Begin function "
137
<< GlobalValue::dropLLVMManglingEscape(F.getName()) << '\n';
138
}
139
140
auto Section = getObjFileLowering().SectionForGlobal(&F, TM);
141
MF->setSection(Section);
142
}
143
144
void SPIRVAsmPrinter::outputOpFunctionEnd() {
145
MCInst FunctionEndInst;
146
FunctionEndInst.setOpcode(SPIRV::OpFunctionEnd);
147
outputMCInst(FunctionEndInst);
148
}
149
150
// Emit OpFunctionEnd at the end of MF and clear BBNumToRegMap.
151
void SPIRVAsmPrinter::emitFunctionBodyEnd() {
152
outputOpFunctionEnd();
153
MAI->BBNumToRegMap.clear();
154
}
155
156
void SPIRVAsmPrinter::emitOpLabel(const MachineBasicBlock &MBB) {
157
MCInst LabelInst;
158
LabelInst.setOpcode(SPIRV::OpLabel);
159
LabelInst.addOperand(MCOperand::createReg(MAI->getOrCreateMBBRegister(MBB)));
160
outputMCInst(LabelInst);
161
++NLabels;
162
}
163
164
void SPIRVAsmPrinter::emitBasicBlockStart(const MachineBasicBlock &MBB) {
165
assert(!MBB.empty() && "MBB is empty!");
166
167
// If it's the first MBB in MF, it has OpFunction and OpFunctionParameter, so
168
// OpLabel should be output after them.
169
if (MBB.getNumber() == MF->front().getNumber()) {
170
for (const MachineInstr &MI : MBB)
171
if (MI.getOpcode() == SPIRV::OpFunction)
172
return;
173
// TODO: this case should be checked by the verifier.
174
report_fatal_error("OpFunction is expected in the front MBB of MF");
175
}
176
emitOpLabel(MBB);
177
}
178
179
void SPIRVAsmPrinter::printOperand(const MachineInstr *MI, int OpNum,
180
raw_ostream &O) {
181
const MachineOperand &MO = MI->getOperand(OpNum);
182
183
switch (MO.getType()) {
184
case MachineOperand::MO_Register:
185
O << SPIRVInstPrinter::getRegisterName(MO.getReg());
186
break;
187
188
case MachineOperand::MO_Immediate:
189
O << MO.getImm();
190
break;
191
192
case MachineOperand::MO_FPImmediate:
193
O << MO.getFPImm();
194
break;
195
196
case MachineOperand::MO_MachineBasicBlock:
197
O << *MO.getMBB()->getSymbol();
198
break;
199
200
case MachineOperand::MO_GlobalAddress:
201
O << *getSymbol(MO.getGlobal());
202
break;
203
204
case MachineOperand::MO_BlockAddress: {
205
MCSymbol *BA = GetBlockAddressSymbol(MO.getBlockAddress());
206
O << BA->getName();
207
break;
208
}
209
210
case MachineOperand::MO_ExternalSymbol:
211
O << *GetExternalSymbolSymbol(MO.getSymbolName());
212
break;
213
214
case MachineOperand::MO_JumpTableIndex:
215
case MachineOperand::MO_ConstantPoolIndex:
216
default:
217
llvm_unreachable("<unknown operand type>");
218
}
219
}
220
221
bool SPIRVAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
222
const char *ExtraCode, raw_ostream &O) {
223
if (ExtraCode && ExtraCode[0])
224
return true; // Invalid instruction - SPIR-V does not have special modifiers
225
226
printOperand(MI, OpNo, O);
227
return false;
228
}
229
230
static bool isFuncOrHeaderInstr(const MachineInstr *MI,
231
const SPIRVInstrInfo *TII) {
232
return TII->isHeaderInstr(*MI) || MI->getOpcode() == SPIRV::OpFunction ||
233
MI->getOpcode() == SPIRV::OpFunctionParameter;
234
}
235
236
void SPIRVAsmPrinter::outputMCInst(MCInst &Inst) {
237
OutStreamer->emitInstruction(Inst, *OutContext.getSubtargetInfo());
238
}
239
240
void SPIRVAsmPrinter::outputInstruction(const MachineInstr *MI) {
241
SPIRVMCInstLower MCInstLowering;
242
MCInst TmpInst;
243
MCInstLowering.lower(MI, TmpInst, MAI);
244
outputMCInst(TmpInst);
245
}
246
247
void SPIRVAsmPrinter::emitInstruction(const MachineInstr *MI) {
248
SPIRV_MC::verifyInstructionPredicates(MI->getOpcode(),
249
getSubtargetInfo().getFeatureBits());
250
251
if (!MAI->getSkipEmission(MI))
252
outputInstruction(MI);
253
254
// Output OpLabel after OpFunction and OpFunctionParameter in the first MBB.
255
const MachineInstr *NextMI = MI->getNextNode();
256
if (!MAI->hasMBBRegister(*MI->getParent()) && isFuncOrHeaderInstr(MI, TII) &&
257
(!NextMI || !isFuncOrHeaderInstr(NextMI, TII))) {
258
assert(MI->getParent()->getNumber() == MF->front().getNumber() &&
259
"OpFunction is not in the front MBB of MF");
260
emitOpLabel(*MI->getParent());
261
}
262
}
263
264
void SPIRVAsmPrinter::outputModuleSection(SPIRV::ModuleSectionType MSType) {
265
for (MachineInstr *MI : MAI->getMSInstrs(MSType))
266
outputInstruction(MI);
267
}
268
269
void SPIRVAsmPrinter::outputDebugSourceAndStrings(const Module &M) {
270
// Output OpSourceExtensions.
271
for (auto &Str : MAI->SrcExt) {
272
MCInst Inst;
273
Inst.setOpcode(SPIRV::OpSourceExtension);
274
addStringImm(Str.first(), Inst);
275
outputMCInst(Inst);
276
}
277
// Output OpSource.
278
MCInst Inst;
279
Inst.setOpcode(SPIRV::OpSource);
280
Inst.addOperand(MCOperand::createImm(static_cast<unsigned>(MAI->SrcLang)));
281
Inst.addOperand(
282
MCOperand::createImm(static_cast<unsigned>(MAI->SrcLangVersion)));
283
outputMCInst(Inst);
284
}
285
286
void SPIRVAsmPrinter::outputOpExtInstImports(const Module &M) {
287
for (auto &CU : MAI->ExtInstSetMap) {
288
unsigned Set = CU.first;
289
Register Reg = CU.second;
290
MCInst Inst;
291
Inst.setOpcode(SPIRV::OpExtInstImport);
292
Inst.addOperand(MCOperand::createReg(Reg));
293
addStringImm(getExtInstSetName(
294
static_cast<SPIRV::InstructionSet::InstructionSet>(Set)),
295
Inst);
296
outputMCInst(Inst);
297
}
298
}
299
300
void SPIRVAsmPrinter::outputOpMemoryModel() {
301
MCInst Inst;
302
Inst.setOpcode(SPIRV::OpMemoryModel);
303
Inst.addOperand(MCOperand::createImm(static_cast<unsigned>(MAI->Addr)));
304
Inst.addOperand(MCOperand::createImm(static_cast<unsigned>(MAI->Mem)));
305
outputMCInst(Inst);
306
}
307
308
// Before the OpEntryPoints' output, we need to add the entry point's
309
// interfaces. The interface is a list of IDs of global OpVariable instructions.
310
// These declare the set of global variables from a module that form
311
// the interface of this entry point.
312
void SPIRVAsmPrinter::outputEntryPoints() {
313
// Find all OpVariable IDs with required StorageClass.
314
DenseSet<Register> InterfaceIDs;
315
for (MachineInstr *MI : MAI->GlobalVarList) {
316
assert(MI->getOpcode() == SPIRV::OpVariable);
317
auto SC = static_cast<SPIRV::StorageClass::StorageClass>(
318
MI->getOperand(2).getImm());
319
// Before version 1.4, the interface's storage classes are limited to
320
// the Input and Output storage classes. Starting with version 1.4,
321
// the interface's storage classes are all storage classes used in
322
// declaring all global variables referenced by the entry point call tree.
323
if (ST->isAtLeastSPIRVVer(VersionTuple(1, 4)) ||
324
SC == SPIRV::StorageClass::Input || SC == SPIRV::StorageClass::Output) {
325
MachineFunction *MF = MI->getMF();
326
Register Reg = MAI->getRegisterAlias(MF, MI->getOperand(0).getReg());
327
InterfaceIDs.insert(Reg);
328
}
329
}
330
331
// Output OpEntryPoints adding interface args to all of them.
332
for (MachineInstr *MI : MAI->getMSInstrs(SPIRV::MB_EntryPoints)) {
333
SPIRVMCInstLower MCInstLowering;
334
MCInst TmpInst;
335
MCInstLowering.lower(MI, TmpInst, MAI);
336
for (Register Reg : InterfaceIDs) {
337
assert(Reg.isValid());
338
TmpInst.addOperand(MCOperand::createReg(Reg));
339
}
340
outputMCInst(TmpInst);
341
}
342
}
343
344
// Create global OpCapability instructions for the required capabilities.
345
void SPIRVAsmPrinter::outputGlobalRequirements() {
346
// Abort here if not all requirements can be satisfied.
347
MAI->Reqs.checkSatisfiable(*ST);
348
349
for (const auto &Cap : MAI->Reqs.getMinimalCapabilities()) {
350
MCInst Inst;
351
Inst.setOpcode(SPIRV::OpCapability);
352
Inst.addOperand(MCOperand::createImm(Cap));
353
outputMCInst(Inst);
354
}
355
356
// Generate the final OpExtensions with strings instead of enums.
357
for (const auto &Ext : MAI->Reqs.getExtensions()) {
358
MCInst Inst;
359
Inst.setOpcode(SPIRV::OpExtension);
360
addStringImm(getSymbolicOperandMnemonic(
361
SPIRV::OperandCategory::ExtensionOperand, Ext),
362
Inst);
363
outputMCInst(Inst);
364
}
365
// TODO add a pseudo instr for version number.
366
}
367
368
void SPIRVAsmPrinter::outputExtFuncDecls() {
369
// Insert OpFunctionEnd after each declaration.
370
SmallVectorImpl<MachineInstr *>::iterator
371
I = MAI->getMSInstrs(SPIRV::MB_ExtFuncDecls).begin(),
372
E = MAI->getMSInstrs(SPIRV::MB_ExtFuncDecls).end();
373
for (; I != E; ++I) {
374
outputInstruction(*I);
375
if ((I + 1) == E || (*(I + 1))->getOpcode() == SPIRV::OpFunction)
376
outputOpFunctionEnd();
377
}
378
}
379
380
// Encode LLVM type by SPIR-V execution mode VecTypeHint.
381
static unsigned encodeVecTypeHint(Type *Ty) {
382
if (Ty->isHalfTy())
383
return 4;
384
if (Ty->isFloatTy())
385
return 5;
386
if (Ty->isDoubleTy())
387
return 6;
388
if (IntegerType *IntTy = dyn_cast<IntegerType>(Ty)) {
389
switch (IntTy->getIntegerBitWidth()) {
390
case 8:
391
return 0;
392
case 16:
393
return 1;
394
case 32:
395
return 2;
396
case 64:
397
return 3;
398
default:
399
llvm_unreachable("invalid integer type");
400
}
401
}
402
if (FixedVectorType *VecTy = dyn_cast<FixedVectorType>(Ty)) {
403
Type *EleTy = VecTy->getElementType();
404
unsigned Size = VecTy->getNumElements();
405
return Size << 16 | encodeVecTypeHint(EleTy);
406
}
407
llvm_unreachable("invalid type");
408
}
409
410
static void addOpsFromMDNode(MDNode *MDN, MCInst &Inst,
411
SPIRV::ModuleAnalysisInfo *MAI) {
412
for (const MDOperand &MDOp : MDN->operands()) {
413
if (auto *CMeta = dyn_cast<ConstantAsMetadata>(MDOp)) {
414
Constant *C = CMeta->getValue();
415
if (ConstantInt *Const = dyn_cast<ConstantInt>(C)) {
416
Inst.addOperand(MCOperand::createImm(Const->getZExtValue()));
417
} else if (auto *CE = dyn_cast<Function>(C)) {
418
Register FuncReg = MAI->getFuncReg(CE);
419
assert(FuncReg.isValid());
420
Inst.addOperand(MCOperand::createReg(FuncReg));
421
}
422
}
423
}
424
}
425
426
void SPIRVAsmPrinter::outputExecutionModeFromMDNode(
427
Register Reg, MDNode *Node, SPIRV::ExecutionMode::ExecutionMode EM,
428
unsigned ExpectMDOps, int64_t DefVal) {
429
MCInst Inst;
430
Inst.setOpcode(SPIRV::OpExecutionMode);
431
Inst.addOperand(MCOperand::createReg(Reg));
432
Inst.addOperand(MCOperand::createImm(static_cast<unsigned>(EM)));
433
addOpsFromMDNode(Node, Inst, MAI);
434
// reqd_work_group_size and work_group_size_hint require 3 operands,
435
// if metadata contains less operands, just add a default value
436
unsigned NodeSz = Node->getNumOperands();
437
if (ExpectMDOps > 0 && NodeSz < ExpectMDOps)
438
for (unsigned i = NodeSz; i < ExpectMDOps; ++i)
439
Inst.addOperand(MCOperand::createImm(DefVal));
440
outputMCInst(Inst);
441
}
442
443
void SPIRVAsmPrinter::outputExecutionModeFromNumthreadsAttribute(
444
const Register &Reg, const Attribute &Attr,
445
SPIRV::ExecutionMode::ExecutionMode EM) {
446
assert(Attr.isValid() && "Function called with an invalid attribute.");
447
448
MCInst Inst;
449
Inst.setOpcode(SPIRV::OpExecutionMode);
450
Inst.addOperand(MCOperand::createReg(Reg));
451
Inst.addOperand(MCOperand::createImm(static_cast<unsigned>(EM)));
452
453
SmallVector<StringRef> NumThreads;
454
Attr.getValueAsString().split(NumThreads, ',');
455
assert(NumThreads.size() == 3 && "invalid numthreads");
456
for (uint32_t i = 0; i < 3; ++i) {
457
uint32_t V;
458
[[maybe_unused]] bool Result = NumThreads[i].getAsInteger(10, V);
459
assert(!Result && "Failed to parse numthreads");
460
Inst.addOperand(MCOperand::createImm(V));
461
}
462
463
outputMCInst(Inst);
464
}
465
466
void SPIRVAsmPrinter::outputExecutionMode(const Module &M) {
467
NamedMDNode *Node = M.getNamedMetadata("spirv.ExecutionMode");
468
if (Node) {
469
for (unsigned i = 0; i < Node->getNumOperands(); i++) {
470
MCInst Inst;
471
Inst.setOpcode(SPIRV::OpExecutionMode);
472
addOpsFromMDNode(cast<MDNode>(Node->getOperand(i)), Inst, MAI);
473
outputMCInst(Inst);
474
}
475
}
476
for (auto FI = M.begin(), E = M.end(); FI != E; ++FI) {
477
const Function &F = *FI;
478
// Only operands of OpEntryPoint instructions are allowed to be
479
// <Entry Point> operands of OpExecutionMode
480
if (F.isDeclaration() || !isEntryPoint(F))
481
continue;
482
Register FReg = MAI->getFuncReg(&F);
483
assert(FReg.isValid());
484
if (MDNode *Node = F.getMetadata("reqd_work_group_size"))
485
outputExecutionModeFromMDNode(FReg, Node, SPIRV::ExecutionMode::LocalSize,
486
3, 1);
487
if (Attribute Attr = F.getFnAttribute("hlsl.numthreads"); Attr.isValid())
488
outputExecutionModeFromNumthreadsAttribute(
489
FReg, Attr, SPIRV::ExecutionMode::LocalSize);
490
if (MDNode *Node = F.getMetadata("work_group_size_hint"))
491
outputExecutionModeFromMDNode(FReg, Node,
492
SPIRV::ExecutionMode::LocalSizeHint, 3, 1);
493
if (MDNode *Node = F.getMetadata("intel_reqd_sub_group_size"))
494
outputExecutionModeFromMDNode(FReg, Node,
495
SPIRV::ExecutionMode::SubgroupSize, 0, 0);
496
if (MDNode *Node = F.getMetadata("vec_type_hint")) {
497
MCInst Inst;
498
Inst.setOpcode(SPIRV::OpExecutionMode);
499
Inst.addOperand(MCOperand::createReg(FReg));
500
unsigned EM = static_cast<unsigned>(SPIRV::ExecutionMode::VecTypeHint);
501
Inst.addOperand(MCOperand::createImm(EM));
502
unsigned TypeCode = encodeVecTypeHint(getMDOperandAsType(Node, 0));
503
Inst.addOperand(MCOperand::createImm(TypeCode));
504
outputMCInst(Inst);
505
}
506
if (ST->isOpenCLEnv() && !M.getNamedMetadata("spirv.ExecutionMode") &&
507
!M.getNamedMetadata("opencl.enable.FP_CONTRACT")) {
508
MCInst Inst;
509
Inst.setOpcode(SPIRV::OpExecutionMode);
510
Inst.addOperand(MCOperand::createReg(FReg));
511
unsigned EM = static_cast<unsigned>(SPIRV::ExecutionMode::ContractionOff);
512
Inst.addOperand(MCOperand::createImm(EM));
513
outputMCInst(Inst);
514
}
515
}
516
}
517
518
void SPIRVAsmPrinter::outputAnnotations(const Module &M) {
519
outputModuleSection(SPIRV::MB_Annotations);
520
// Process llvm.global.annotations special global variable.
521
for (auto F = M.global_begin(), E = M.global_end(); F != E; ++F) {
522
if ((*F).getName() != "llvm.global.annotations")
523
continue;
524
const GlobalVariable *V = &(*F);
525
const ConstantArray *CA = cast<ConstantArray>(V->getOperand(0));
526
for (Value *Op : CA->operands()) {
527
ConstantStruct *CS = cast<ConstantStruct>(Op);
528
// The first field of the struct contains a pointer to
529
// the annotated variable.
530
Value *AnnotatedVar = CS->getOperand(0)->stripPointerCasts();
531
if (!isa<Function>(AnnotatedVar))
532
report_fatal_error("Unsupported value in llvm.global.annotations");
533
Function *Func = cast<Function>(AnnotatedVar);
534
Register Reg = MAI->getFuncReg(Func);
535
if (!Reg.isValid()) {
536
std::string DiagMsg;
537
raw_string_ostream OS(DiagMsg);
538
AnnotatedVar->print(OS);
539
DiagMsg = "Unknown function in llvm.global.annotations: " + DiagMsg;
540
report_fatal_error(DiagMsg.c_str());
541
}
542
543
// The second field contains a pointer to a global annotation string.
544
GlobalVariable *GV =
545
cast<GlobalVariable>(CS->getOperand(1)->stripPointerCasts());
546
547
StringRef AnnotationString;
548
getConstantStringInfo(GV, AnnotationString);
549
MCInst Inst;
550
Inst.setOpcode(SPIRV::OpDecorate);
551
Inst.addOperand(MCOperand::createReg(Reg));
552
unsigned Dec = static_cast<unsigned>(SPIRV::Decoration::UserSemantic);
553
Inst.addOperand(MCOperand::createImm(Dec));
554
addStringImm(AnnotationString, Inst);
555
outputMCInst(Inst);
556
}
557
}
558
}
559
560
void SPIRVAsmPrinter::outputModuleSections() {
561
const Module *M = MMI->getModule();
562
// Get the global subtarget to output module-level info.
563
ST = static_cast<const SPIRVTargetMachine &>(TM).getSubtargetImpl();
564
TII = ST->getInstrInfo();
565
MAI = &SPIRVModuleAnalysis::MAI;
566
assert(ST && TII && MAI && M && "Module analysis is required");
567
// Output instructions according to the Logical Layout of a Module:
568
// 1,2. All OpCapability instructions, then optional OpExtension instructions.
569
outputGlobalRequirements();
570
// 3. Optional OpExtInstImport instructions.
571
outputOpExtInstImports(*M);
572
// 4. The single required OpMemoryModel instruction.
573
outputOpMemoryModel();
574
// 5. All entry point declarations, using OpEntryPoint.
575
outputEntryPoints();
576
// 6. Execution-mode declarations, using OpExecutionMode or OpExecutionModeId.
577
outputExecutionMode(*M);
578
// 7a. Debug: all OpString, OpSourceExtension, OpSource, and
579
// OpSourceContinued, without forward references.
580
outputDebugSourceAndStrings(*M);
581
// 7b. Debug: all OpName and all OpMemberName.
582
outputModuleSection(SPIRV::MB_DebugNames);
583
// 7c. Debug: all OpModuleProcessed instructions.
584
outputModuleSection(SPIRV::MB_DebugModuleProcessed);
585
// 8. All annotation instructions (all decorations).
586
outputAnnotations(*M);
587
// 9. All type declarations (OpTypeXXX instructions), all constant
588
// instructions, and all global variable declarations. This section is
589
// the first section to allow use of: OpLine and OpNoLine debug information;
590
// non-semantic instructions with OpExtInst.
591
outputModuleSection(SPIRV::MB_TypeConstVars);
592
// 10. All function declarations (functions without a body).
593
outputExtFuncDecls();
594
// 11. All function definitions (functions with a body).
595
// This is done in regular function output.
596
}
597
598
bool SPIRVAsmPrinter::doInitialization(Module &M) {
599
ModuleSectionsEmitted = false;
600
// We need to call the parent's one explicitly.
601
return AsmPrinter::doInitialization(M);
602
}
603
604
// Force static initialization.
605
extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeSPIRVAsmPrinter() {
606
RegisterAsmPrinter<SPIRVAsmPrinter> X(getTheSPIRV32Target());
607
RegisterAsmPrinter<SPIRVAsmPrinter> Y(getTheSPIRV64Target());
608
RegisterAsmPrinter<SPIRVAsmPrinter> Z(getTheSPIRVLogicalTarget());
609
}
610
611