source: CLRX/CLRadeonExtender/trunk/amdasm/AsmROCmFormat.cpp @ 2587

Last change on this file since 2587 was 2587, checked in by matszpk, 3 years ago

CLRadeonExtender: Update AsmROCm.

File size: 17.0 KB
Line 
1/*
2 *  CLRadeonExtender - Unofficial OpenCL Radeon Extensions Library
3 *  Copyright (C) 2014-2016 Mateusz Szpakowski
4 *
5 *  This library is free software; you can redistribute it and/or
6 *  modify it under the terms of the GNU Lesser General Public
7 *  License as published by the Free Software Foundation; either
8 *  version 2.1 of the License, or (at your option) any later version.
9 *
10 *  This library is distributed in the hope that it will be useful,
11 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 *  Lesser General Public License for more details.
14 *
15 *  You should have received a copy of the GNU Lesser General Public
16 *  License along with this library; if not, write to the Free Software
17 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
18 */
19
20#include <CLRX/Config.h>
21#include <cstring>
22#include <string>
23#include <vector>
24#include <utility>
25#include <algorithm>
26#include <CLRX/utils/Utilities.h>
27#include <CLRX/amdasm/Assembler.h>
28#include "AsmInternals.h"
29
30using namespace CLRX;
31
32static const char* rocmPseudoOpNamesTbl[] =
33{
34    "call_convention", "codeversion", "config",
35    "control_directive", "debug_private_segment_buffer_sgpr",
36    "debug_wavefront_private_segment_offset_sgpr",
37    "debugmode", "dims", "dx10clamp",
38    "exceptions", "floatmode", "gds_segment_size",
39    "group_segment_align", "ieeemode", "kcode",
40    "kcodeend", "kernarg_segment_align",
41    "kernarg_segment_size", "kernel_code_entry_offset",
42    "kernel_code_prefetch_offset", "kernel_code_prefetch_size",
43    "localsize", "machine", "max_scratch_backing_memory",
44    "pgmrsrc1", "pgmrsrc2", "priority", "private_segment_align",
45    "privmode", "reserved_sgpr_count", "reserved_sgpr_first",
46    "reserved_vgpr_count", "reserved_vgpr_first",
47    "runtime_loader_kernel_symbol",
48    "scratchbuffer", "sgprsnum", "tgsize",
49    "use_debug_enabled", "use_dispatch_id",
50    "use_dispatch_ptr", "use_dynamic_call_stack",
51    "use_flat_scratch_init", "use_grid_workgroup_count",
52    "use_kernarg_segment_ptr", "use_ordered_append_gds",
53    "use_private_segment_size", "use_ptr64", "use_queue_ptr",
54    "use_private_segment_buffer", "use_xnack_enabled",
55    "userdatanum", "vgprsnum", "wavefront_sgpr_count",
56    "wavefront_size", "workitem_vgpr_count",
57    "workgroup_fbarrier_count", "workgroup_group_segment_size",
58    "workitem_private_segment_size"
59};
60
61enum
62{
63    ROCMOP_CALL_CONVENTION, ROCMOP_CODEVERSION, ROCMOP_CONFIG,
64    ROCMOP_CONTROL_DIRECTIVE, ROCMOP_DEBUG_PRIVATE_SEGMENT_BUFFER_SGPR,
65    ROCMOP_DEBUG_WAVEFRONT_PRIVATE_SEGMENT_OFFSET_SGPR,
66    ROCMOP_DEBUGMODE, ROCMOP_DIMS, ROCMOP_DX10CLAMP,
67    ROCMOP_EXCEPTIONS, ROCMOP_FLOATMODE, ROCMOP_GDS_SEGMENT_SIZE,
68    ROCMOP_GROUP_SEGMENT_ALIGN, ROCMOP_IEEEMODE, ROCMOP_KCODE,
69    ROCMOP_KCODEEND, ROCMOP_KERNARG_SEGMENT_ALIGN,
70    ROCMOP_KERNARG_SEGMENT_SIZE, ROCMOP_KERNEL_CODE_ENTRY_OFFSET,
71    ROCMOP_KERNEL_CODE_PREFETCH_OFFSET, ROCMOP_KERNEL_CODE_PREFETCH_SIZE,
72    ROCMOP_LOCALSIZE, ROCMOP_MACHINE, ROCMOP_MAX_SCRATCH_BACKING_MEMORY,
73    ROCMOP_PGMRSRC1, ROCMOP_PGMRSRC2, ROCMOP_PRIORITY, ROCMOP_PRIVATE_SEGMENT_ALIGN,
74    ROCMOP_PRIVMODE, ROCMOP_RESERVED_SGPR_COUNT, ROCMOP_RESERVED_SGPR_FIRST,
75    ROCMOP_RESERVED_VGPR_COUNT, ROCMOP_RESERVED_VGPR_FIRST,
76    ROCMOP_RUNTIME_LOADER_KERNEL_SYMBOL,
77    ROCMOP_SCRATCHBUFFER, ROCMOP_SGPRSNUM, ROCMOP_TGSIZE,
78    ROCMOP_USE_DEBUG_ENABLED, ROCMOP_USE_DISPATCH_ID,
79    ROCMOP_USE_DISPATCH_PTR, ROCMOP_USE_DYNAMIC_CALL_STACK,
80    ROCMOP_USE_FLAT_SCRATCH_INIT, ROCMOP_USE_GRID_WORKGROUP_COUNT,
81    ROCMOP_USE_KERNARG_SEGMENT_PTR, ROCMOP_USE_ORDERED_APPEND_GDS,
82    ROCMOP_USE_PRIVATE_SEGMENT_SIZE, ROCMOP_USE_PTR64, ROCMOP_USE_QUEUE_PTR,
83    ROCMOP_USE_PRIVATE_SEGMENT_BUFFER, ROCMOP_USE_XNACK_ENABLED,
84    ROCMOP_USERDATANUM, ROCMOP_VGPRSNUM, ROCMOP_WAVEFRONT_SGPR_COUNT,
85    ROCMOP_WAVEFRONT_SIZE, ROCMOP_WORKITEM_VGPR_COUNT,
86    ROCMOP_WORKGROUP_FBARRIER_COUNT, ROCMOP_WORKGROUP_GROUP_SEGMENT_SIZE,
87    ROCMOP_WORKITEM_PRIVATE_SEGMENT_SIZE
88};
89
90/*
91 * ROCm format handler
92 */
93
94AsmROCmHandler::AsmROCmHandler(Assembler& assembler): AsmFormatHandler(assembler),
95             output{}, codeSection(0), commentSection(ASMSECT_NONE),
96             extraSectionCount(0)
97{
98    assembler.currentKernel = ASMKERN_GLOBAL;
99    assembler.currentSection = 0;
100    sections.push_back({ ASMKERN_GLOBAL, AsmSectionType::CODE,
101                ELFSECTID_TEXT, ".text" });
102    currentKcodeKernel = ASMKERN_GLOBAL;
103    savedSection = 0;
104}
105
106cxuint AsmROCmHandler::addKernel(const char* kernelName)
107{
108    cxuint thisKernel = output.symbols.size();
109    cxuint thisSection = sections.size();
110    output.addEmptyKernel(kernelName);
111    /// add kernel config section
112    sections.push_back({ thisKernel, AsmSectionType::CONFIG, ELFSECTID_UNDEF, nullptr });
113    kernelStates.push_back({ thisSection, nullptr, ASMSECT_NONE, thisSection });
114   
115    if (assembler.currentKernel == ASMKERN_GLOBAL)
116        savedSection = assembler.currentSection;
117   
118    assembler.currentKernel = thisKernel;
119    assembler.currentSection = thisSection;
120    return thisKernel;
121}
122
123cxuint AsmROCmHandler::addSection(const char* sectionName, cxuint kernelId)
124{
125    const cxuint thisSection = sections.size();
126    Section section;
127    section.kernelId = ASMKERN_GLOBAL;  // we ignore input kernelId, we go to main
128       
129    if (::strcmp(sectionName, ".text") == 0) // code
130    {
131        if (codeSection!=ASMSECT_NONE)
132            throw AsmFormatException("Only one section '.text' can be in binary");
133        codeSection = thisSection;
134        section.type = AsmSectionType::CODE;
135        section.elfBinSectId = ELFSECTID_TEXT;
136        section.name = ".text"; // set static name (available by whole lifecycle)
137    }
138    else if (::strcmp(sectionName, ".comment") == 0) // comment
139    {
140        if (commentSection!=ASMSECT_NONE)
141            throw AsmFormatException("Only one section '.comment' can be in binary");
142        commentSection = thisSection;
143        section.type = AsmSectionType::GALLIUM_COMMENT;
144        section.elfBinSectId = ELFSECTID_COMMENT;
145        section.name = ".comment"; // set static name (available by whole lifecycle)
146    }
147    else
148    {
149        auto out = extraSectionMap.insert(std::make_pair(CString(sectionName),
150                    thisSection));
151        if (!out.second)
152            throw AsmFormatException("Section already exists");
153        section.type = AsmSectionType::EXTRA_SECTION;
154        section.elfBinSectId = extraSectionCount++;
155        /// reference entry is available and unchangeable by whole lifecycle of section map
156        section.name = out.first->first.c_str();
157    }
158    sections.push_back(section);
159   
160    assembler.currentKernel = ASMKERN_GLOBAL;
161    assembler.currentSection = thisSection;
162    return thisSection;
163}
164
165cxuint AsmROCmHandler::getSectionId(const char* sectionName) const
166{
167    if (::strcmp(sectionName, ".text") == 0) // code
168        return codeSection;
169    else if (::strcmp(sectionName, ".comment") == 0) // comment
170        return commentSection;
171    else
172    {
173        SectionMap::const_iterator it = extraSectionMap.find(sectionName);
174        if (it != extraSectionMap.end())
175            return it->second;
176    }
177    return ASMSECT_NONE;
178}
179
180void AsmROCmHandler::setCurrentKernel(cxuint kernel)
181{
182    if (kernel != ASMKERN_GLOBAL && kernel >= kernelStates.size())
183        throw AsmFormatException("KernelId out of range");
184   
185    if (assembler.currentKernel == ASMKERN_GLOBAL)
186        savedSection = assembler.currentSection;
187    else // if kernel
188        kernelStates[assembler.currentKernel].savedSection = assembler.currentSection;
189   
190    assembler.currentKernel = kernel;
191    if (kernel != ASMKERN_GLOBAL)
192        assembler.currentSection = kernelStates[kernel].savedSection;
193    else // default main section
194        assembler.currentSection = savedSection;
195}
196
197void AsmROCmHandler::setCurrentSection(cxuint sectionId)
198{
199    if (sectionId >= sections.size())
200        throw AsmFormatException("SectionId out of range");
201   
202    if (assembler.currentKernel == ASMKERN_GLOBAL)
203        savedSection = assembler.currentSection;
204    else // if kernel
205        kernelStates[assembler.currentKernel].savedSection = assembler.currentSection;
206   
207    assembler.currentSection = sectionId;
208    assembler.currentKernel = sections[sectionId].kernelId;
209}
210
211
212AsmFormatHandler::SectionInfo AsmROCmHandler::getSectionInfo(cxuint sectionId) const
213{
214    if (sectionId >= sections.size())
215        throw AsmFormatException("Section doesn't exists");
216   
217    AsmFormatHandler::SectionInfo info;
218    info.type = sections[sectionId].type;
219    info.flags = 0;
220    if (info.type == AsmSectionType::CODE)
221        info.flags = ASMSECT_ADDRESSABLE | ASMSECT_WRITEABLE;
222    else if (info.type != AsmSectionType::CONFIG)
223        info.flags = ASMSECT_ADDRESSABLE | ASMSECT_WRITEABLE | ASMSECT_ABS_ADDRESSABLE;
224   
225    info.name = sections[sectionId].name;
226    return info;
227}
228
229void AsmROCmHandler::restoreKcodeCurrentAllocRegs()
230{
231    if (currentKcodeKernel != ASMKERN_GLOBAL)
232    {
233        Kernel& newKernel = kernelStates[currentKcodeKernel];
234        assembler.isaAssembler->setAllocatedRegisters(newKernel.allocRegs,
235                            newKernel.allocRegFlags);
236    }
237}
238
239void AsmROCmHandler::saveKcodeCurrentAllocRegs()
240{
241    if (currentKcodeKernel != ASMKERN_GLOBAL)
242    {   // save other state
243        size_t regTypesNum;
244        Kernel& oldKernel = kernelStates[currentKcodeKernel];
245        const cxuint* regs = assembler.isaAssembler->getAllocatedRegisters(
246                            regTypesNum, oldKernel.allocRegFlags);
247        std::copy(regs, regs+2, oldKernel.allocRegs);
248    }
249}
250
251
252void AsmROCmHandler::handleLabel(const CString& label)
253{
254    if (assembler.sections[assembler.currentSection].type != AsmSectionType::CODE)
255        return;
256    auto kit = assembler.kernelMap.find(label);
257    if (kit == assembler.kernelMap.end())
258        return;
259    if (!kcodeSelection.empty())
260        return; // do not change if inside kcode
261    // save other state
262    saveKcodeCurrentAllocRegs();
263    // restore this state
264    currentKcodeKernel = kit->second;
265    restoreKcodeCurrentAllocRegs();
266}
267
268void AsmROCmHandler::Kernel::initializeKernelConfig()
269{
270    config.reset(new ROCmKernelConfig{});
271    ::memset(config.get(), 0, sizeof(ROCmKernelConfig));
272}
273
274namespace CLRX
275{
276
277bool AsmROCmPseudoOps::checkPseudoOpName(const CString& string)
278{
279    if (string.empty() || string[0] != '.')
280        return false;
281    const size_t pseudoOp = binaryFind(rocmPseudoOpNamesTbl, rocmPseudoOpNamesTbl +
282                sizeof(rocmPseudoOpNamesTbl)/sizeof(char*), string.c_str()+1,
283               CStringLess()) - rocmPseudoOpNamesTbl;
284    return pseudoOp < sizeof(rocmPseudoOpNamesTbl)/sizeof(char*);
285}
286   
287void AsmROCmPseudoOps::doConfig(AsmROCmHandler& handler, const char* pseudoOpPlace,
288                  const char* linePtr)
289{
290    Assembler& asmr = handler.assembler;
291    const char* end = asmr.line + asmr.lineSize;
292    if (asmr.currentKernel==ASMKERN_GLOBAL)
293    {
294        asmr.printError(pseudoOpPlace, "Kernel config can be defined only inside kernel");
295        return;
296    }
297   
298    if (handler.sections[asmr.currentSection].type != AsmSectionType::CONFIG)
299    {
300        asmr.printError(pseudoOpPlace, "Configuration outside kernel definition");
301        return;
302    }
303    skipSpacesToEnd(linePtr, end);
304    if (!checkGarbagesAtEnd(asmr, linePtr))
305        return;
306    handler.kernelStates[asmr.currentKernel].initializeKernelConfig();
307}
308
309void AsmROCmPseudoOps::doControlDirective(AsmROCmHandler& handler,
310              const char* pseudoOpPlace, const char* linePtr)
311{
312    Assembler& asmr = handler.assembler;
313    const char* end = asmr.line + asmr.lineSize;
314    if (asmr.currentKernel==ASMKERN_GLOBAL)
315    {
316        asmr.printError(pseudoOpPlace, "Kernel control directive can be defined "
317                    "only inside kernel");
318        return;
319    }
320    skipSpacesToEnd(linePtr, end);
321    if (!checkGarbagesAtEnd(asmr, linePtr))
322        return;
323   
324    AsmROCmHandler::Kernel& kernel = handler.kernelStates[asmr.currentKernel];
325    if (kernel.ctrlDirSection == ASMSECT_NONE)
326    {
327        cxuint thisSection = handler.sections.size();
328        handler.sections.push_back({ asmr.currentKernel,
329            AsmSectionType::ROCM_CONFIG_CTRL_DIRECTIVE,
330            ELFSECTID_UNDEF, nullptr });
331        kernel.ctrlDirSection = thisSection;
332    }
333    asmr.goToSection(pseudoOpPlace, kernel.ctrlDirSection);
334    handler.kernelStates[asmr.currentKernel].initializeKernelConfig();
335}
336
337void AsmROCmPseudoOps::setConfigValue(AsmROCmHandler& handler, const char* pseudoOpPlace,
338                  const char* linePtr, ROCmConfigValueTarget target)
339{
340}
341
342void AsmROCmPseudoOps::setConfigBoolValue(AsmROCmHandler& handler,
343          const char* pseudoOpPlace, const char* linePtr, ROCmConfigValueTarget target)
344{
345}
346
347void AsmROCmPseudoOps::setDimensions(AsmROCmHandler& handler, const char* pseudoOpPlace,
348                  const char* linePtr)
349{
350}
351
352void AsmROCmPseudoOps::doKCode(AsmROCmHandler& handler, const char* pseudoOpPlace,
353                  const char* linePtr)
354{
355}
356
357void AsmROCmPseudoOps::doKCodeEnd(AsmROCmHandler& handler, const char* pseudoOpPlace,
358                  const char* linePtr)
359{
360}
361
362void AsmROCmPseudoOps::updateKCodeSel(AsmROCmHandler& handler,
363                  const std::vector<cxuint>& oldset)
364{
365}
366
367}
368
369bool AsmROCmHandler::parsePseudoOp(const CString& firstName, const char* stmtPlace,
370               const char* linePtr)
371{
372    const size_t pseudoOp = binaryFind(rocmPseudoOpNamesTbl, rocmPseudoOpNamesTbl +
373                    sizeof(rocmPseudoOpNamesTbl)/sizeof(char*), firstName.c_str()+1,
374                   CStringLess()) - rocmPseudoOpNamesTbl;
375   
376    switch(pseudoOp)
377    {
378        case ROCMOP_CALL_CONVENTION:
379            break;
380        case ROCMOP_CODEVERSION:
381            break;
382        case ROCMOP_CONFIG:
383            break;
384        case ROCMOP_CONTROL_DIRECTIVE:
385            break;
386        case ROCMOP_DEBUG_PRIVATE_SEGMENT_BUFFER_SGPR:
387            break;
388        case ROCMOP_DEBUG_WAVEFRONT_PRIVATE_SEGMENT_OFFSET_SGPR:
389            break;
390        case ROCMOP_DEBUGMODE:
391            break;
392        case ROCMOP_DIMS:
393            break;
394        case ROCMOP_DX10CLAMP:
395            break;
396        case ROCMOP_EXCEPTIONS:
397            break;
398        case ROCMOP_FLOATMODE:
399            break;
400        case ROCMOP_GDS_SEGMENT_SIZE:
401            break;
402        case ROCMOP_GROUP_SEGMENT_ALIGN:
403            break;
404        case ROCMOP_IEEEMODE:
405            break;
406        case ROCMOP_KCODE:
407            break;
408        case ROCMOP_KCODEEND:
409            break;
410        case ROCMOP_KERNARG_SEGMENT_ALIGN:
411            break;
412        case ROCMOP_KERNARG_SEGMENT_SIZE:
413            break;
414        case ROCMOP_KERNEL_CODE_ENTRY_OFFSET:
415            break;
416        case ROCMOP_KERNEL_CODE_PREFETCH_OFFSET:
417            break;
418        case ROCMOP_KERNEL_CODE_PREFETCH_SIZE:
419            break;
420        case ROCMOP_LOCALSIZE:
421            break;
422        case ROCMOP_MACHINE:
423            break;
424        case ROCMOP_MAX_SCRATCH_BACKING_MEMORY:
425            break;
426        case ROCMOP_PGMRSRC1:
427            break;
428        case ROCMOP_PGMRSRC2:
429            break;
430        case ROCMOP_PRIORITY:
431            break;
432        case ROCMOP_PRIVATE_SEGMENT_ALIGN:
433            break;
434        case ROCMOP_PRIVMODE:
435            break;
436        case ROCMOP_RESERVED_SGPR_COUNT:
437            break;
438        case ROCMOP_RESERVED_SGPR_FIRST:
439            break;
440        case ROCMOP_RESERVED_VGPR_COUNT:
441            break;
442        case ROCMOP_RESERVED_VGPR_FIRST:
443            break;
444        case ROCMOP_RUNTIME_LOADER_KERNEL_SYMBOL:
445            break;
446        case ROCMOP_SCRATCHBUFFER:
447            break;
448        case ROCMOP_SGPRSNUM:
449            break;
450        case ROCMOP_TGSIZE:
451            break;
452        case ROCMOP_USE_DEBUG_ENABLED:
453            break;
454        case ROCMOP_USE_DISPATCH_ID:
455            break;
456        case ROCMOP_USE_DISPATCH_PTR:
457            break;
458        case ROCMOP_USE_DYNAMIC_CALL_STACK:
459            break;
460        case ROCMOP_USE_FLAT_SCRATCH_INIT:
461            break;
462        case ROCMOP_USE_GRID_WORKGROUP_COUNT:
463            break;
464        case ROCMOP_USE_KERNARG_SEGMENT_PTR:
465            break;
466        case ROCMOP_USE_ORDERED_APPEND_GDS:
467            break;
468        case ROCMOP_USE_PRIVATE_SEGMENT_SIZE:
469            break;
470        case ROCMOP_USE_PTR64:
471            break;
472        case ROCMOP_USE_QUEUE_PTR:
473            break;
474        case ROCMOP_USE_PRIVATE_SEGMENT_BUFFER:
475            break;
476        case ROCMOP_USE_XNACK_ENABLED:
477            break;
478        case ROCMOP_USERDATANUM:
479            break;
480        case ROCMOP_VGPRSNUM:
481            break;
482        case ROCMOP_WAVEFRONT_SGPR_COUNT:
483            break;
484        case ROCMOP_WAVEFRONT_SIZE:
485            break;
486        case ROCMOP_WORKITEM_VGPR_COUNT:
487            break;
488        case ROCMOP_WORKGROUP_FBARRIER_COUNT:
489            break;
490        case ROCMOP_WORKGROUP_GROUP_SEGMENT_SIZE:
491            break;
492        case ROCMOP_WORKITEM_PRIVATE_SEGMENT_SIZE:
493            break;
494        default:
495            return false;
496    }
497    return true;
498}
499
500bool AsmROCmHandler::prepareBinary()
501{
502    return false;
503}
504
505void AsmROCmHandler::writeBinary(std::ostream& os) const
506{
507}
508
509void AsmROCmHandler::writeBinary(Array<cxbyte>& array) const
510{
511}
Note: See TracBrowser for help on using the repository browser.