1 /*========================== begin_copyright_notice ============================
2
3 Copyright (C) 2017-2021 Intel Corporation
4
5 SPDX-License-Identifier: MIT
6
7 ============================= end_copyright_notice ===========================*/
8
9 #include <sstream>
10 #include <fstream>
11 #include <regex>
12 #include "visa_igc_common_header.h"
13 #include "Common_ISA.h"
14 #include "Common_ISA_util.h"
15 #include "Common_ISA_framework.h"
16 #include "JitterDataStruct.h"
17 #include "VISAKernel.h"
18
19 #include "IsaDisassembly.h"
20 #include "IsaVerification.h"
21
22 #if defined(_DEBUG) && (defined(_WIN32) || defined(_WIN64))
23 #include <Windows.h>
24 #endif
25
26 #define SIZE_VALUE m_kernel_data_size
27 #define SIZE_VALUE_INST m_instruction_size
28
29 namespace CisaFramework
30 {
31
createCisaInstruction(ISA_Opcode opcode,unsigned char exec_size,unsigned char modifier,PredicateOpnd pred,VISA_opnd ** opnd,int numOpnds,const VISA_INST_Desc * inst_desc)32 int CisaInst::createCisaInstruction(
33 ISA_Opcode opcode,
34 unsigned char exec_size,
35 unsigned char modifier,
36 PredicateOpnd pred,
37 VISA_opnd** opnd,
38 int numOpnds,
39 const VISA_INST_Desc* inst_desc)
40 {
41 uint8_t subOpcode = 0;
42 bool hasSubOpcode = false;
43 int descOpndCount = inst_desc->opnd_num;
44
45 for (int i = 0; i < descOpndCount; i++)
46 {
47 if (inst_desc->opnd_desc[i].opnd_type == OPND_SUBOPCODE)
48 {
49 descOpndCount += inst_desc->getSubInstDesc((uint8_t) opnd[i]->_opnd.other_opnd).opnd_num;
50 hasSubOpcode = true;
51 subOpcode = static_cast<uint8_t>(opnd[0]->_opnd.other_opnd);
52 break;
53 }
54 }
55
56 // TODO: move the FIXME below above this if statment and
57 // int implicitOperands = 0;
58 // for (...) // parent op descriptors
59 // if (type == EXEC_SIZE || type == PRED)
60 // implicitOperands++;
61 // for (...) // subop op descriptors
62 // if (type == EXEC_SIZE || type == PRED)
63 // implicitOperands++;
64 // TODO: rename numOpnds to explicitOpnds to be clear
65 // TODO: rename descOpndCount to descOpndsToEncodeCount
66 //
67 // compare (descOpndCount != explicitOpnds + implicitOperands)
68 // mismatch assert
69 if (opcode != ISA_FCALL)
70 {
71 // != doens't work here because predication and exec size are treated
72 // differently; it might be descOpndCount == numOpnds (+ HAS_EXEC) (+ HAS_PRED)
73 // if (descOpndCount != numOpnds)
74 if (descOpndCount < numOpnds)
75 {
76 std::string msg = "Number of operands mismatch between CISA instruction description and value passed in.";
77 std::cerr << msg << ": " << descOpndCount << " " << numOpnds << "\n";
78 MUST_BE_TRUE(false, msg);
79 }
80 }
81
82 m_inst_desc = inst_desc;
83 m_cisa_instruction.opnd_count = numOpnds;
84 m_cisa_instruction.opcode = opcode;
85 m_cisa_instruction.execsize = exec_size;
86 m_cisa_instruction.modifier = modifier;
87 m_cisa_instruction.pred = pred;
88 m_cisa_instruction.opnd_array = (VISA_opnd**)m_mem.alloc(sizeof(VISA_opnd*) * numOpnds);
89 std::copy_n(opnd, numOpnds, m_cisa_instruction.opnd_array);
90 m_cisa_instruction.isa_type = inst_desc->type;
91
92 // FIXME: this is a mess and needs to be cleaned up
93 // I think this comment refers to merging the subopcode and opcode case
94 // that is we're hunting for EXEC_SIZE and PRED operands in both the
95 // suboperand and parent
96 for (int i = 0; i < descOpndCount; i++)
97 {
98 if (inst_desc->opnd_desc[i].opnd_type == OPND_EXECSIZE ||
99 inst_desc->opnd_desc[i].opnd_type == OPND_PRED)
100 {
101 m_size += static_cast<short>(Get_VISA_Type_Size((VISA_Type)inst_desc->opnd_desc[i].data_type));
102 }
103 }
104 if (hasSubOpcode)
105 {
106 int numOpnd = inst_desc->getSubInstDesc(subOpcode).opnd_num;
107 for (int i = 0; i < numOpnd; i++)
108 {
109 OpndDesc desc = inst_desc->getSubInstDesc(subOpcode).opnd_desc[i];
110 if (desc.opnd_type == OPND_EXECSIZE || desc.opnd_type == OPND_PRED)
111 {
112 m_size += static_cast<short>(Get_VISA_Type_Size((VISA_Type)desc.data_type));
113 }
114 }
115 }
116
117
118 for (int i = 0; i < numOpnds; i++)
119 {
120 if (opnd[i] == NULL)
121 {
122 assert(0);
123 std::cerr << "ONE OF THE OPERANDS IS NULL!\n";
124 return VISA_FAILURE;
125 }
126 m_size += opnd[i]->size;
127 }
128
129 return VISA_SUCCESS;
130 }
131
CisaBinary(CISA_IR_Builder * builder)132 CisaBinary::CisaBinary(CISA_IR_Builder* builder) :
133 m_mem(4096),
134 m_header_size(0),
135 m_total_size(0),
136 m_bytes_written_cisa_buffer(0),
137 m_header_buffer(NULL),
138 m_options(builder->getOptions()),
139 parent(builder)
140 {
141 memset(&m_header, 0, sizeof(common_isa_header));
142 }
143
144
initKernel(int kernelIndex,VISAKernelImpl * kernel)145 void CisaBinary::initKernel(int kernelIndex, VISAKernelImpl * kernel)
146 {
147 unsigned functionIndex = 0; // separating function and kernel index
148 MUST_BE_TRUE(kernelIndex < (m_upper_bound_kernels + m_upper_bound_functions) && kernelIndex >= 0,
149 "Invalid kernelIndex in CisaBinary initialization.\n");
150
151 int nameLen = (int) strlen(kernel->getName());
152
153 if (this->getMajorVersion())
154 {
155 if (kernel->getIsKernel())
156 kernelIndex = m_header.num_kernels++;
157 else
158 {
159 m_header.num_functions++;
160 kernel->GetFunctionId(functionIndex);
161 }
162 }
163
164 if (kernel->getIsKernel())
165 {
166 m_header.kernels[kernelIndex].name_len = (unsigned short) nameLen;
167 m_header.kernels[kernelIndex].name = (char*)m_mem.alloc(nameLen + 1);
168 m_header.kernels[kernelIndex].name[nameLen] = 0;
169 memcpy_s(m_header.kernels[kernelIndex].name, m_header.kernels[kernelIndex].name_len, kernel->getName(), m_header.kernels[kernelIndex].name_len);
170
171 m_header.kernels[kernelIndex].offset = 0; //will be set later during finalize
172 m_header.kernels[kernelIndex].size = kernel->getCisaBinarySize();
173 m_header.kernels[kernelIndex].cisa_binary_buffer = kernel->getCisaBinaryBuffer(); //buffer containing entire kernel
174 m_header.kernels[kernelIndex].input_offset = kernel->getInputOffset(); //for now relative to the beginning of the kernel object
175
176 //Workaround for patching in FE. This way space for data structures is allocated
177 unsigned int numGenBinariesWillBePatched = kernel->getOptions()->getuInt32Option(vISA_NumGenBinariesWillBePatched);
178 m_header.kernels[kernelIndex].num_gen_binaries = static_cast<unsigned char>(numGenBinariesWillBePatched);
179 m_header.kernels[kernelIndex].gen_binaries = (gen_binary_info *)m_mem.alloc(sizeof(gen_binary_info)* (int)m_header.kernels[kernelIndex].num_gen_binaries);
180
181 for (int i = 0; i < m_header.kernels[kernelIndex].num_gen_binaries; i++)
182 {
183 m_header.kernels[kernelIndex].gen_binaries[i].binary_offset = 0;
184 m_header.kernels[kernelIndex].gen_binaries[i].binary_offset = 0;
185 m_header.kernels[kernelIndex].gen_binaries[i].platform = 0;
186 }
187 }
188
189 if (!kernel->getIsKernel())
190 {
191 m_header.functions[functionIndex].linkage = 0; // deprecated and MBZ
192 m_header.functions[functionIndex].name_len = (unsigned short) nameLen;
193 m_header.functions[functionIndex].name = (char*)m_mem.alloc(nameLen + 1);
194 memcpy_s(m_header.functions[functionIndex].name, m_header.functions[functionIndex].name_len, kernel->getName(), m_header.functions[functionIndex].name_len);
195 m_header.functions[functionIndex].name[nameLen] = 0;
196 m_header.functions[functionIndex].offset = 0; //will be set later during finalize
197 m_header.functions[functionIndex].size = kernel->getCisaBinarySize();
198 m_header.functions[functionIndex].cisa_binary_buffer = kernel->getCisaBinaryBuffer(); //buffer containing entire kernel
199 }
200 }
201
writeInToCisaHeaderBuffer(const void * value,int size)202 unsigned long CisaBinary::writeInToCisaHeaderBuffer(const void * value, int size)
203 {
204 MUST_BE_TRUE(m_bytes_written_cisa_buffer + size <= m_header_size,
205 "Size of CISA instructions header buffer is exceeded.");
206
207 memcpy_s(&m_header_buffer[m_bytes_written_cisa_buffer], size, value, size);
208 m_bytes_written_cisa_buffer += size;
209
210 return m_bytes_written_cisa_buffer;
211 }
212
213 /*
214 calculates total size of the header and sets all the kernel offsets from the beginning of the file
215 */
finalizeCisaBinary()216 int CisaBinary::finalizeCisaBinary()
217 {
218 m_bytes_written_cisa_buffer = 0;
219
220 m_total_size = m_header_size = m_header.getSizeInBinary();
221
222 m_header_buffer = (char *)this->m_mem.alloc(m_header_size);
223 memset(m_header_buffer, 0, m_header_size);
224
225 writeInToCisaHeaderBuffer(&m_header.magic_number, sizeof(m_header.magic_number));
226
227 // we must use the latest vISA version since the internal data structures always use it
228 uint8_t major = COMMON_ISA_MAJOR_VER;
229 uint8_t minor = COMMON_ISA_MINOR_VER;
230 writeInToCisaHeaderBuffer(&major, sizeof(uint8_t));
231 writeInToCisaHeaderBuffer(&minor, sizeof(uint8_t));
232
233 writeInToCisaHeaderBuffer(&m_header.num_kernels, sizeof(m_header.num_kernels));
234
235 for (int i = 0; i < m_header.num_kernels; i++)
236 {
237 writeInToCisaHeaderBuffer(&m_header.kernels[i].name_len, sizeof(m_header.kernels[i].name_len));
238 writeInToCisaHeaderBuffer(m_header.kernels[i].name, m_header.kernels[i].name_len);
239
240 //setting offset to the compiled cisa binary kernel
241 //to correct offset in final cisa binary
242 m_header.kernels[i].offset = m_total_size;
243 //for patching later if genx binary is generated
244 this->m_kernelOffsetLocationsArray[i] = m_bytes_written_cisa_buffer;
245 writeInToCisaHeaderBuffer(&m_header.kernels[i].offset, sizeof(m_header.kernels[i].offset));
246
247 writeInToCisaHeaderBuffer(&m_header.kernels[i].size, sizeof(m_header.kernels[i].size));
248
249 //this was originally set to relative offset from the
250 //compiled cisa binary kernel
251 //changing it to absoute offset from the beginning of the
252 //cisa binary
253 m_header.kernels[i].input_offset += m_total_size;
254 this->m_kernelInputOffsetLocationsArray[i] = m_bytes_written_cisa_buffer;
255 writeInToCisaHeaderBuffer(&m_header.kernels[i].input_offset, sizeof(m_header.kernels[i].input_offset));
256
257 //setting offset to the compiled genx binary kernel
258 //to correct offset in final cisa binary
259 m_total_size += m_header.kernels[i].size;
260 m_total_size += m_header.kernels[i].binary_size;
261
262 assert(m_header.kernels[i].variable_reloc_symtab.num_syms == 0 && "variable relocation not supported");
263 writeInToCisaHeaderBuffer(&m_header.kernels[i].variable_reloc_symtab.num_syms, sizeof(m_header.kernels[i].variable_reloc_symtab.num_syms));
264
265 assert(m_header.kernels[i].function_reloc_symtab.num_syms == 0 && "function relocation not supported");
266 writeInToCisaHeaderBuffer(&m_header.kernels[i].function_reloc_symtab.num_syms, sizeof(m_header.kernels[i].function_reloc_symtab.num_syms));
267
268 //for now gen binaries
269 this->m_krenelBinaryInfoLocationsArray[i] = m_bytes_written_cisa_buffer;
270 writeInToCisaHeaderBuffer(&m_header.kernels[i].num_gen_binaries, sizeof(m_header.kernels[i].num_gen_binaries));
271 for (int j = 0; j < m_header.kernels[i].num_gen_binaries; j++)
272 {
273 m_header.kernels[i].gen_binaries[j].binary_offset = m_total_size;
274 m_header.kernels[i].gen_binaries[j].platform = 0;
275 m_header.kernels[i].gen_binaries[j].binary_size = 0;
276 writeInToCisaHeaderBuffer(&m_header.kernels[i].gen_binaries[j].platform, sizeof(m_header.kernels[i].gen_binaries[j].platform));
277 writeInToCisaHeaderBuffer(&m_header.kernels[i].gen_binaries[j].binary_offset, sizeof(m_header.kernels[i].gen_binaries[j].binary_offset));
278 writeInToCisaHeaderBuffer(&m_header.kernels[i].gen_binaries[j].binary_size, sizeof(m_header.kernels[i].gen_binaries[j].binary_size));
279
280 m_total_size += m_header.kernels[i].gen_binaries[j].binary_size;
281 }
282 }
283
284 // file-scope variables are no longer supported
285 uint16_t numFileScopeVariables = 0;
286 writeInToCisaHeaderBuffer(&numFileScopeVariables, sizeof(numFileScopeVariables));
287
288 writeInToCisaHeaderBuffer(&m_header.num_functions, sizeof(m_header.num_functions));
289
290 for (int i = 0; i < m_header.num_functions; i++)
291 {
292 writeInToCisaHeaderBuffer(&m_header.functions[i].linkage, sizeof(m_header.functions[i].linkage));
293 writeInToCisaHeaderBuffer(&m_header.functions[i].name_len, sizeof(m_header.functions[i].name_len));
294 writeInToCisaHeaderBuffer(m_header.functions[i].name, m_header.functions[i].name_len);
295
296 //setting offset to the compiled cisa binary kernel
297 //to correct offset in final cisa binary
298 m_header.functions[i].offset = m_total_size;
299 this->m_functionOffsetLocationsArray[i] = this->m_bytes_written_cisa_buffer;
300 writeInToCisaHeaderBuffer(&m_header.functions[i].offset, sizeof(m_header.functions[i].offset));
301
302 writeInToCisaHeaderBuffer(&m_header.functions[i].size, sizeof(m_header.functions[i].size));
303
304 assert(m_header.functions[i].variable_reloc_symtab.num_syms == 0 && "variable relocation not supported");
305 writeInToCisaHeaderBuffer(&m_header.functions[i].variable_reloc_symtab.num_syms, sizeof(m_header.functions[i].variable_reloc_symtab.num_syms));
306
307 assert(m_header.functions[i].function_reloc_symtab.num_syms == 0 && "function relocation not supported");
308 writeInToCisaHeaderBuffer(&m_header.functions[i].function_reloc_symtab.num_syms, sizeof(m_header.functions[i].function_reloc_symtab.num_syms));
309
310 m_total_size += m_header.functions[i].size;
311 }
312
313 return VISA_SUCCESS;
314 }
315
dumpToStream(std::ostream * os)316 int CisaBinary::dumpToStream(std::ostream * os)
317 {
318 os->write(this->m_header_buffer, this->m_header_size);
319
320 for (int i = 0; i < m_header.num_kernels; i++)
321 {
322 os->write(m_header.kernels[i].cisa_binary_buffer, m_header.kernels[i].size);
323 os->write(m_header.kernels[i].genx_binary_buffer, m_header.kernels[i].binary_size);
324 }
325
326 for (int i = 0; i < m_header.num_functions; i++)
327 {
328 os->write(m_header.functions[i].cisa_binary_buffer, m_header.functions[i].size);
329 }
330 return VISA_SUCCESS;
331 }
332
dumpToFile(std::string binFileName)333 int CisaBinary::dumpToFile(std::string binFileName)
334 {
335 if (binFileName == "")
336 {
337 binFileName = "temp.isa";
338 }
339 std::ofstream os(binFileName.c_str(), std::ios::binary|std::ios::out);
340 if (!os)
341 {
342 std::cerr << binFileName << ": unable to open output file\n";
343 return VISA_FAILURE;
344 }
345 int result = dumpToStream(&os);
346 os.close();
347 return result;
348 }
349
writeIsaAsmFile(std::string filename,std::string isaasmStr) const350 void CisaBinary::writeIsaAsmFile(std::string filename, std::string isaasmStr) const
351 {
352 std::ofstream isaasm;
353 isaasm.open(filename.c_str());
354
355 if (isaasm.fail())
356 {
357 MUST_BE_TRUE(false, "Failed to write CISA ASM to file");
358 }
359
360 isaasm << isaasmStr;
361 isaasm.close();
362 }
363
patchKernel(int index,unsigned int genxBufferSize,void * buffer,int platform)364 void CisaBinary::patchKernel(int index, unsigned int genxBufferSize, void * buffer, int platform)
365 {
366 int copySize = 0;
367 m_header.kernels[index].offset += genxBinariesSize;
368 copySize = sizeof(m_header.kernels[index].offset);
369 memcpy_s(&m_header_buffer[this->m_kernelOffsetLocationsArray[index]], copySize, &m_header.kernels[index].offset, copySize);
370
371 m_header.kernels[index].input_offset += genxBinariesSize;
372 copySize = sizeof(m_header.kernels[index].input_offset);
373 memcpy_s(&m_header_buffer[this->m_kernelInputOffsetLocationsArray[index]], copySize, &m_header.kernels[index].input_offset, copySize);
374
375 int offsetGenBinary = this->m_krenelBinaryInfoLocationsArray[index];
376 m_header.kernels[index].num_gen_binaries = 1;
377 copySize = sizeof(m_header.kernels[index].num_gen_binaries);
378 memcpy_s(&m_header_buffer[offsetGenBinary], copySize, &m_header.kernels[index].num_gen_binaries, copySize);
379 offsetGenBinary += sizeof(m_header.kernels[index].num_gen_binaries);
380
381 m_header.kernels[index].gen_binaries[0].platform = static_cast<unsigned char>(platform);
382 copySize = sizeof(m_header.kernels[index].gen_binaries[0].platform);
383 memcpy_s(&m_header_buffer[offsetGenBinary], copySize, &m_header.kernels[index].gen_binaries[0].platform, copySize);
384 offsetGenBinary += sizeof(m_header.kernels[index].gen_binaries[0].platform);
385
386 m_header.kernels[index].gen_binaries[0].binary_offset += genxBinariesSize;
387 copySize = sizeof(m_header.kernels[index].gen_binaries[0].binary_offset);
388 memcpy_s(&m_header_buffer[offsetGenBinary], copySize, &m_header.kernels[index].gen_binaries[0].binary_offset, copySize);
389 offsetGenBinary += sizeof(m_header.kernels[index].gen_binaries[0].binary_offset);
390
391 m_header.kernels[index].gen_binaries[0].binary_size = genxBufferSize;
392 copySize = sizeof(m_header.kernels[index].gen_binaries[0].binary_size);
393 memcpy_s(&m_header_buffer[offsetGenBinary], copySize, &m_header.kernels[index].gen_binaries[0].binary_size, copySize);
394 offsetGenBinary += sizeof(m_header.kernels[index].gen_binaries[0].binary_size);
395
396 m_header.kernels[index].genx_binary_buffer = (char *) buffer;
397 m_header.kernels[index].binary_size = genxBufferSize;
398 this->genxBinariesSize+= genxBufferSize;
399 }
400
patchFunctionWithGenBinary(int index,unsigned int genxBufferSize,char * buffer)401 void CisaBinary::patchFunctionWithGenBinary(int index, unsigned int genxBufferSize, char* buffer)
402 {
403 m_header.functions[index].offset += genxBinariesSize;
404 size_t copySize = sizeof(m_header.functions[index].offset);
405 memcpy_s(&m_header_buffer[this->m_functionOffsetLocationsArray[index]], copySize, &m_header.functions[index].offset, copySize);
406
407 m_header.functions[index].genx_binary_buffer = buffer;
408
409 this->genxBinariesSize += genxBufferSize;
410 }
411
patchFunction(int index,unsigned genxBufferSize)412 void CisaBinary::patchFunction(int index, unsigned genxBufferSize)
413 {
414 m_header.functions[index].offset += genxBinariesSize;
415 size_t copySize = sizeof(m_header.functions[index].offset);
416 memcpy_s(&m_header_buffer[this->m_functionOffsetLocationsArray[index]], copySize, &m_header.functions[index].offset, copySize);
417
418 this->genxBinariesSize += genxBufferSize;
419 }
420
getFmtKernelForISADump(const VISAKernelImpl * kernel,const std::list<VISAKernelImpl * > & kernels) const421 const VISAKernelImpl* CisaBinary::getFmtKernelForISADump(const VISAKernelImpl* kernel,
422 const std::list<VISAKernelImpl*>& kernels) const
423 {
424 // Assuming there's no too many payload kernels. Use the logic in
425 // CisaBinary::isaDump to select the kernel for format provider.
426 if (!kernel->getIsPayload())
427 return kernel;
428
429 assert(!kernels.empty());
430 VISAKernelImpl* fmtKernel = kernels.front();
431 for (VISAKernelImpl* k : kernels)
432 {
433 if (k == kernel)
434 break;
435 if (k->getIsKernel())
436 fmtKernel = k;
437 }
438 return fmtKernel;
439 }
440
isaDump(const VISAKernelImpl * kernel,const VISAKernelImpl * fmtKernel) const441 std::string CisaBinary::isaDump(const VISAKernelImpl* kernel,
442 const VISAKernelImpl* fmtKernel) const
443 {
444 std::stringstream sstr;
445 VISAKernel_format_provider fmt(fmtKernel);
446
447 sstr << fmt.printKernelHeader(m_header);
448
449 std::list<CisaFramework::CisaInst *>::const_iterator inst_iter = kernel->getInstructionListBegin();
450 std::list<CisaFramework::CisaInst *>::const_iterator inst_iter_end = kernel->getInstructionListEnd();
451 for (; inst_iter != inst_iter_end; inst_iter++)
452 {
453 CisaFramework::CisaInst * cisa_inst = *inst_iter;
454 const CISA_INST * inst = cisa_inst->getCISAInst();
455 sstr << printInstruction(&fmt, inst, kernel->getOptions()) << "\n";
456 }
457
458 return sstr.str();
459 }
460
isaDump(const std::list<VISAKernelImpl * > & kernels,const Options * options) const461 int CisaBinary::isaDump(
462 const std::list<VISAKernelImpl*>& kernels, const Options* options) const
463 {
464 #ifdef IS_RELEASE_DLL
465 return VISA_SUCCESS;
466 #else
467 bool dump = m_options->getOption(vISA_GenerateISAASM);
468 if (!dump)
469 return VISA_SUCCESS;
470
471 struct ScopedFile
472 {
473 FILE* isaasmListFile = nullptr;
474 ~ScopedFile()
475 {
476 if (isaasmListFile)
477 fclose(isaasmListFile);
478 }
479 } ILFile;
480
481 if (options->getOption(vISA_GenerateISAASM) && options->getOption(vISA_GenIsaAsmList))
482 {
483 if (options->getOption(vISA_IsaasmNamesFileUsed))
484 {
485 const char* isaasmNamesFile = nullptr;
486 options->getOption(vISA_ISAASMNamesFile, isaasmNamesFile);
487 if (isaasmNamesFile && (ILFile.isaasmListFile = fopen(isaasmNamesFile, "w")) == nullptr)
488 {
489 std::cerr << "Cannot open file " << isaasmNamesFile << "\n";
490 return VISA_FAILURE;
491 }
492 }
493 else
494 {
495 if ((ILFile.isaasmListFile = fopen("isaasmListFile.txt", "w")) == nullptr)
496 {
497 std::cerr << "Cannot open isaasmListFile.txt\n";
498 return VISA_FAILURE;
499 }
500 }
501 }
502
503 std::vector<std::string> failedFiles;
504 VISAKernelImpl* mainKernel = kernels.front();
505 for (VISAKernelImpl* kTemp : kernels)
506 {
507 unsigned funcId = 0;
508 if (!(m_options->getOption(vISA_DumpvISA) && m_options->getOption(vISA_IsaasmNamesFileUsed)))
509 {
510 std::stringstream sstr;
511 std::stringstream asmName;
512
513 if (kTemp->getIsKernel())
514 {
515 mainKernel = kTemp;
516 asmName << kTemp->getOutputAsmPath();
517 }
518 else if (kTemp->getIsFunction())
519 {
520 //function 0 has kernel_f0.visaasm
521 kTemp->GetFunctionId(funcId);
522 if (mainKernel) {
523 asmName << mainKernel->getOutputAsmPath();
524 } else {
525 // No mainKernel, use the function name instead
526 asmName << kTemp->getName();
527 }
528
529 asmName << "_f";
530 asmName << funcId;
531 }
532 else
533 {
534 assert(kTemp->getIsPayload());
535 asmName << mainKernel->getOutputAsmPath();
536 asmName << "_payload";
537 }
538 asmName << ".visaasm";
539 if (ILFile.isaasmListFile && m_options->getOption(vISA_GenIsaAsmList))
540 fputs(std::string(asmName.str() + "\n").c_str(), ILFile.isaasmListFile);
541
542 VISAKernelImpl* fmtKernel = kTemp->getIsPayload() ? mainKernel : kTemp;
543 sstr << isaDump(kTemp, fmtKernel);
544
545 // from other shader dumps we sometimes get non-existent paths
546 // fallback to a default file name in the current working directory
547 // for that case
548 std::string asmFileName = asmName.str();
549 if (allowDump(*m_options, asmFileName))
550 {
551 FILE* f = fopen(asmFileName.c_str(), "w");
552 if (f) {
553 fclose(f);
554 }
555 else {
556 asmFileName = "default.visaasm";
557 }
558 writeIsaAsmFile(asmFileName, sstr.str());
559 }
560 }
561 }
562
563 return VISA_SUCCESS;
564 #endif // IS_RELEASE_DLL
565 }
566
allowDump(const Options & options,const std::string & fileName)567 bool allowDump(const Options& options, const std::string &fileName)
568 {
569 const char* regex = options.getOptionCstr(vISA_ShaderDumpFilter);
570 if (!regex || *regex == '\0')
571 return true;
572
573 std::regex fileRegex(regex);
574
575 return std::regex_search(fileName, fileRegex);
576 }
577
578 }
579
580 // It's unfortunate we have to define vISAVerifier functions here due to the #include mess..
run(VISAKernelImpl * kernel)581 void vISAVerifier::run(VISAKernelImpl* kernel)
582 {
583 irBuilder = kernel->getIRBuilder();
584 verifyKernelHeader();
585 for (auto iter = kernel->getInstructionListBegin(), iterEnd = kernel->getInstructionListEnd();
586 iter != iterEnd; ++iter)
587 {
588 auto inst = (*iter)->getCISAInst();
589 verifyInstruction(inst);
590 }
591 finalize();
592 }
593