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

Last change on this file since 2584 was 2584, checked in by matszpk, 4 years ago

CLRadeonExtender: AsmROCm: Add ROCmKernelConfig to Kernelstate
Asm: add ROCm support (add pseudo-ops and format handling). fixed checkPseudoOpName (add AmdCL2 pseudo-op checking).

File size: 9.7 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    "config", "debugmode", "dims", "dx10clamp",
35    "exceptions", "floatmode",
36    "ieeemode", "kcode", "kcodeend",
37    "localsize", "pgmrsrc1", "pgmrsrc2", "priority",
38    "privmode", "scratchbuffer", "sgprsnum", "tgsize",
39    "userdatanum", "vgprsnum"
40};
41
42
43/*
44 * ROCm format handler
45 */
46
47AsmROCmHandler::AsmROCmHandler(Assembler& assembler): AsmFormatHandler(assembler),
48             output{}, codeSection(0), commentSection(ASMSECT_NONE),
49             extraSectionCount(0)
50{
51    assembler.currentKernel = ASMKERN_GLOBAL;
52    assembler.currentSection = 0;
53    sections.push_back({ ASMKERN_GLOBAL, AsmSectionType::CODE,
54                ELFSECTID_TEXT, ".text" });
55    currentKcodeKernel = ASMKERN_GLOBAL;
56    savedSection = 0;
57}
58
59cxuint AsmROCmHandler::addKernel(const char* kernelName)
60{
61    cxuint thisKernel = output.symbols.size();
62    cxuint thisSection = sections.size();
63    output.addEmptyKernel(kernelName);
64    /// add kernel config section
65    sections.push_back({ thisKernel, AsmSectionType::CONFIG, ELFSECTID_UNDEF, nullptr });
66    kernelStates.push_back({ thisSection, 0, nullptr, ASMSECT_NONE, thisSection });
67   
68    if (assembler.currentKernel == ASMKERN_GLOBAL)
69        savedSection = assembler.currentSection;
70   
71    assembler.currentKernel = thisKernel;
72    assembler.currentSection = thisSection;
73    return thisKernel;
74}
75
76cxuint AsmROCmHandler::addSection(const char* sectionName, cxuint kernelId)
77{
78    const cxuint thisSection = sections.size();
79    Section section;
80    if (::strcmp(sectionName, ".control_directive") == 0)
81    {
82        if (kernelId == ASMKERN_GLOBAL)
83            throw AsmFormatException(".control_directive section must be "
84                        "defined inside kernel");
85        if (kernelStates[kernelId].ctrlDirSection != ASMSECT_NONE)
86            throw AsmFormatException("Only one section "
87                        "'.control_directive' can be in kernel");
88        kernelStates[kernelId].ctrlDirSection = thisSection;
89        section.type = AsmSectionType::ROCM_CONFIG_CTRL_DIRECTIVE;
90        section.elfBinSectId = ELFSECTID_TEXT; // . in text
91        section.name = ".control_directive";
92    }
93    else // otherwise
94        section.kernelId = ASMKERN_GLOBAL;  // we ignore input kernelId, we go to main
95       
96    if (::strcmp(sectionName, ".text") == 0) // code
97    {
98        if (codeSection!=ASMSECT_NONE)
99            throw AsmFormatException("Only one section '.text' can be in binary");
100        codeSection = thisSection;
101        section.type = AsmSectionType::CODE;
102        section.elfBinSectId = ELFSECTID_TEXT;
103        section.name = ".text"; // set static name (available by whole lifecycle)
104    }
105    else if (::strcmp(sectionName, ".comment") == 0) // comment
106    {
107        if (commentSection!=ASMSECT_NONE)
108            throw AsmFormatException("Only one section '.comment' can be in binary");
109        commentSection = thisSection;
110        section.type = AsmSectionType::GALLIUM_COMMENT;
111        section.elfBinSectId = ELFSECTID_COMMENT;
112        section.name = ".comment"; // set static name (available by whole lifecycle)
113    }
114    else
115    {
116        auto out = extraSectionMap.insert(std::make_pair(CString(sectionName),
117                    thisSection));
118        if (!out.second)
119            throw AsmFormatException("Section already exists");
120        section.type = AsmSectionType::EXTRA_SECTION;
121        section.elfBinSectId = extraSectionCount++;
122        /// reference entry is available and unchangeable by whole lifecycle of section map
123        section.name = out.first->first.c_str();
124    }
125    sections.push_back(section);
126   
127    assembler.currentKernel = ASMKERN_GLOBAL;
128    assembler.currentSection = thisSection;
129    return thisSection;
130}
131
132cxuint AsmROCmHandler::getSectionId(const char* sectionName) const
133{
134    if (::strcmp(sectionName, ".text") == 0) // code
135        return codeSection;
136    else if (::strcmp(sectionName, ".comment") == 0) // comment
137        return commentSection;
138    else if (assembler.currentKernel != ASMKERN_GLOBAL &&
139        ::strcmp(sectionName, ".control_directive") == 0) // code
140        return kernelStates[assembler.currentKernel].ctrlDirSection;
141    else
142    {
143        SectionMap::const_iterator it = extraSectionMap.find(sectionName);
144        if (it != extraSectionMap.end())
145            return it->second;
146    }
147    return ASMSECT_NONE;
148}
149
150void AsmROCmHandler::setCurrentKernel(cxuint kernel)
151{
152    if (kernel != ASMKERN_GLOBAL && kernel >= kernelStates.size())
153        throw AsmFormatException("KernelId out of range");
154   
155    if (assembler.currentKernel == ASMKERN_GLOBAL)
156        savedSection = assembler.currentSection;
157    else // if kernel
158        kernelStates[assembler.currentKernel].savedSection = assembler.currentSection;
159   
160    assembler.currentKernel = kernel;
161    if (kernel != ASMKERN_GLOBAL)
162        assembler.currentSection = kernelStates[kernel].savedSection;
163    else // default main section
164        assembler.currentSection = savedSection;
165}
166
167void AsmROCmHandler::setCurrentSection(cxuint sectionId)
168{
169    if (sectionId >= sections.size())
170        throw AsmFormatException("SectionId out of range");
171   
172    if (assembler.currentKernel == ASMKERN_GLOBAL)
173        savedSection = assembler.currentSection;
174    else // if kernel
175        kernelStates[assembler.currentKernel].savedSection = assembler.currentSection;
176   
177    assembler.currentSection = sectionId;
178    assembler.currentKernel = sections[sectionId].kernelId;
179}
180
181
182AsmFormatHandler::SectionInfo AsmROCmHandler::getSectionInfo(cxuint sectionId) const
183{
184    if (sectionId >= sections.size())
185        throw AsmFormatException("Section doesn't exists");
186   
187    AsmFormatHandler::SectionInfo info;
188    info.type = sections[sectionId].type;
189    info.flags = 0;
190    if (info.type == AsmSectionType::CODE)
191        info.flags = ASMSECT_ADDRESSABLE | ASMSECT_WRITEABLE;
192    else if (info.type != AsmSectionType::CONFIG)
193        info.flags = ASMSECT_ADDRESSABLE | ASMSECT_WRITEABLE | ASMSECT_ABS_ADDRESSABLE;
194   
195    info.name = sections[sectionId].name;
196    return info;
197}
198
199bool AsmROCmHandler::parsePseudoOp(const CString& firstName,
200       const char* stmtPlace, const char* linePtr)
201{
202    return false;
203}
204
205void AsmROCmHandler::restoreKcodeCurrentAllocRegs()
206{
207    if (currentKcodeKernel != ASMKERN_GLOBAL)
208    {
209        Kernel& newKernel = kernelStates[currentKcodeKernel];
210        assembler.isaAssembler->setAllocatedRegisters(newKernel.allocRegs,
211                            newKernel.allocRegFlags);
212    }
213}
214
215void AsmROCmHandler::saveKcodeCurrentAllocRegs()
216{
217    if (currentKcodeKernel != ASMKERN_GLOBAL)
218    {   // save other state
219        size_t regTypesNum;
220        Kernel& oldKernel = kernelStates[currentKcodeKernel];
221        const cxuint* regs = assembler.isaAssembler->getAllocatedRegisters(
222                            regTypesNum, oldKernel.allocRegFlags);
223        std::copy(regs, regs+2, oldKernel.allocRegs);
224    }
225}
226
227
228void AsmROCmHandler::handleLabel(const CString& label)
229{
230    if (assembler.sections[assembler.currentSection].type != AsmSectionType::CODE)
231        return;
232    auto kit = assembler.kernelMap.find(label);
233    if (kit == assembler.kernelMap.end())
234        return;
235    if (!kcodeSelection.empty())
236        return; // do not change if inside kcode
237    // save other state
238    saveKcodeCurrentAllocRegs();
239    // restore this state
240    currentKcodeKernel = kit->second;
241    restoreKcodeCurrentAllocRegs();
242}
243
244namespace CLRX
245{
246
247bool AsmROCmPseudoOps::checkPseudoOpName(const CString& string)
248{
249    return false;
250}
251   
252/* user configuration pseudo-ops */
253void AsmROCmPseudoOps::doConfig(AsmROCmHandler& handler, const char* pseudoOpPlace,
254                  const char* linePtr)
255{
256}
257
258void AsmROCmPseudoOps::setConfigValue(AsmROCmHandler& handler, const char* pseudoOpPlace,
259                  const char* linePtr, ROCmConfigValueTarget target)
260{
261}
262
263void AsmROCmPseudoOps::setConfigBoolValue(AsmROCmHandler& handler,
264          const char* pseudoOpPlace, const char* linePtr, ROCmConfigValueTarget target)
265{
266}
267
268void AsmROCmPseudoOps::setDimensions(AsmROCmHandler& handler, const char* pseudoOpPlace,
269                  const char* linePtr)
270{
271}
272
273void AsmROCmPseudoOps::doKCode(AsmROCmHandler& handler, const char* pseudoOpPlace,
274                  const char* linePtr)
275{
276}
277
278void AsmROCmPseudoOps::doKCodeEnd(AsmROCmHandler& handler, const char* pseudoOpPlace,
279                  const char* linePtr)
280{
281}
282
283void AsmROCmPseudoOps::updateKCodeSel(AsmROCmHandler& handler,
284                  const std::vector<cxuint>& oldset)
285{
286}
287
288}
289
290bool AsmROCmHandler::prepareBinary()
291{
292    return false;
293}
294
295void AsmROCmHandler::writeBinary(std::ostream& os) const
296{
297}
298
299void AsmROCmHandler::writeBinary(Array<cxbyte>& array) const
300{
301}
Note: See TracBrowser for help on using the repository browser.