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