source: CLRX/CLRadeonExtender/trunk/CLRX/amdasm/Assembler.h @ 3803

Last change on this file since 3803 was 3803, checked in by matszpk, 17 months ago

CLRadeonExtender: Add new option '--newROCmBinFormat'.

File size: 30.6 KB
Line 
1/*
2 *  CLRadeonExtender - Unofficial OpenCL Radeon Extensions Library
3 *  Copyright (C) 2014-2018 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/*! \file Assembler.h
20 * \brief an assembler for Radeon GPU's
21 */
22
23#ifndef __CLRX_ASSEMBLER_H__
24#define __CLRX_ASSEMBLER_H__
25
26#include <CLRX/Config.h>
27#include <cstdint>
28#include <string>
29#include <istream>
30#include <ostream>
31#include <iostream>
32#include <vector>
33#include <utility>
34#include <stack>
35#include <list>
36#include <unordered_set>
37#include <unordered_map>
38#include <CLRX/utils/Utilities.h>
39#include <CLRX/amdasm/Commons.h>
40#include <CLRX/amdasm/AsmSource.h>
41#include <CLRX/amdasm/AsmFormats.h>
42#include <CLRX/amdasm/AsmDefs.h>
43
44/// main namespace
45namespace CLRX
46{
47
48enum: Flags
49{
50    ASM_WARNINGS = 1,   ///< enable all warnings for assembler
51    ASM_FORCE_ADD_SYMBOLS = 2,  ///< force add symbols to binary
52    ASM_ALTMACRO = 4,   ///< enable altmacro mode
53    ASM_BUGGYFPLIT = 8, ///< buggy handling of fpliterals (including fp constants)
54    ASM_MACRONOCASE = 16, /// disable case-insensitive naming (default)
55    ASM_OLDMODPARAM = 32,   ///< use old modifier parametrization (values 0 and 1 only)
56    ASM_TESTRESOLVE = (1U<<30), ///< enable resolving symbols if ASM_TESTRUN enabled
57    ASM_TESTRUN = (1U<<31), ///< only for running tests
58    ASM_ALL = FLAGS_ALL&~(ASM_TESTRUN|ASM_TESTRESOLVE|ASM_BUGGYFPLIT|ASM_MACRONOCASE|
59                    ASM_OLDMODPARAM)  ///< all flags
60};
61
62struct AsmRegVar;
63
64/// ISA (register and regvar) Usage handler
65class ISAUsageHandler
66{
67public:
68    /// stgructure that hold read position to store later
69    struct ReadPos
70    {
71        size_t readOffset;  ///< read offset
72        size_t instrStructPos;  ///< position instrStructs
73        size_t regUsagesPos;    ///< position in reg usage
74        size_t regUsages2Pos;   ///< position in regUsage2
75        size_t regVarUsagesPos;    ///< position in regVarUsage
76        uint16_t pushedArgs;    ///< pushed argds number
77        bool useRegMode;        ///< true if in usereg mode
78    };
79protected:
80    std::vector<cxbyte> instrStruct;    ///< structure of register usage
81    std::vector<AsmRegUsageInt> regUsages;  ///< register usage
82    std::vector<AsmRegUsage2Int> regUsages2;  ///< register usage (by .usereg)
83    std::vector<AsmRegVarUsageInt> regVarUsages;    ///< regvar usage
84    const std::vector<cxbyte>& content; ///< code content
85    size_t lastOffset;  ///< last offset
86    size_t readOffset;  ///< read offset
87    size_t instrStructPos;  ///< position in instr struct
88    size_t regUsagesPos;    ///< position in reg usage
89    size_t regUsages2Pos;   ///< position in reg usage 2
90    size_t regVarUsagesPos; ///< position in regvar usage
91    uint16_t pushedArgs;    ///< pushed args
92    cxbyte argPos;      ///< argument position
93    cxbyte argFlags;    ///< ???
94    cxbyte defaultInstrSize;    ///< default instruction size
95    bool isNext;        ///< is next
96    bool useRegMode;    ///< true if in usereg mode
97   
98    void skipBytesInInstrStruct();
99    /// put space to offset
100    void putSpace(size_t offset);
101   
102    /// constructor
103    explicit ISAUsageHandler(const std::vector<cxbyte>& content);
104public:
105    /// destructor
106    virtual ~ISAUsageHandler();
107    /// copy this usage handler
108    virtual ISAUsageHandler* copy() const = 0;
109   
110    /// push regvar or register usage
111    void pushUsage(const AsmRegVarUsage& rvu);
112    /// rewind to start for reading
113    void rewind();
114    /// flush last pending register usages
115    void flush();
116    /// has next regvar usage
117    bool hasNext() const
118    { return isNext; }
119    /// get next usage
120    AsmRegVarUsage nextUsage();
121   
122    /// get reading position
123    ReadPos getReadPos() const
124    {
125        return { readOffset, instrStructPos, regUsagesPos, regUsages2Pos,
126            regVarUsagesPos, pushedArgs, useRegMode };
127    }
128    /// set reading position
129    void setReadPos(const ReadPos rpos)
130    {
131        readOffset = rpos.readOffset;
132        instrStructPos = rpos.instrStructPos;
133        regUsagesPos = rpos.regUsagesPos;
134        regUsages2Pos = rpos.regUsages2Pos;
135        regVarUsagesPos = rpos.regVarUsagesPos;
136        pushedArgs = rpos.pushedArgs;
137        useRegMode = rpos.useRegMode;
138    }
139   
140    /// push regvar or register from usereg pseudo-op
141    void pushUseRegUsage(const AsmRegVarUsage& rvu);
142   
143    /// get RW flags (used by assembler)
144    virtual cxbyte getRwFlags(AsmRegField regField, uint16_t rstart,
145                      uint16_t rend) const = 0;
146    /// get reg pair (used by assembler)
147    virtual std::pair<uint16_t,uint16_t> getRegPair(AsmRegField regField,
148                    cxbyte rwFlags) const = 0;
149    /// get usage dependencies around single instruction
150    virtual void getUsageDependencies(cxuint rvusNum, const AsmRegVarUsage* rvus,
151                    cxbyte* linearDeps, cxbyte* equalToDeps) const = 0;
152};
153
154/// GCN (register and regvar) Usage handler
155class GCNUsageHandler: public ISAUsageHandler
156{
157private:
158    uint16_t archMask;
159public:
160    /// constructor
161    GCNUsageHandler(const std::vector<cxbyte>& content, uint16_t archMask);
162    /// destructor
163    ~GCNUsageHandler();
164   
165    /// copy this usage handler
166    ISAUsageHandler* copy() const;
167   
168    cxbyte getRwFlags(AsmRegField regFied, uint16_t rstart, uint16_t rend) const;
169    std::pair<uint16_t,uint16_t> getRegPair(AsmRegField regField, cxbyte rwFlags) const;
170    void getUsageDependencies(cxuint rvusNum, const AsmRegVarUsage* rvus,
171                    cxbyte* linearDeps, cxbyte* equalToDeps) const;
172};
173
174/// ISA assembler class
175class ISAAssembler: public NonCopyableAndNonMovable
176{
177protected:
178    Assembler& assembler;       ///< assembler
179   
180    /// print warning for position pointed by line pointer
181    void printWarning(const char* linePtr, const char* message);
182    /// print error for position pointed by line pointer
183    void printError(const char* linePtr, const char* message);
184    /// print warning for source position
185    void printWarning(const AsmSourcePos& sourcePos, const char* message);
186    /// print error for source position
187    void printError(const AsmSourcePos& sourcePos, const char* message);
188    /// print warning about integer out of range
189    void printWarningForRange(cxuint bits, uint64_t value, const AsmSourcePos& pos,
190                cxbyte signess = WS_BOTH);
191    void addCodeFlowEntry(cxuint sectionId, const AsmCodeFlowEntry& entry);
192    /// constructor
193    explicit ISAAssembler(Assembler& assembler);
194public:
195    /// destructor
196    virtual ~ISAAssembler();
197    /// create usage handler
198    virtual ISAUsageHandler* createUsageHandler(std::vector<cxbyte>& content) const = 0;
199   
200    /// assemble single line
201    virtual void assemble(const CString& mnemonic, const char* mnemPlace,
202              const char* linePtr, const char* lineEnd, std::vector<cxbyte>& output,
203              ISAUsageHandler* usageHandler) = 0;
204    /// resolve code with location, target and value
205    virtual bool resolveCode(const AsmSourcePos& sourcePos, cxuint targetSectionId,
206                 cxbyte* sectionData, size_t offset, AsmExprTargetType targetType,
207                 cxuint sectionId, uint64_t value) = 0;
208    /// check if name is mnemonic
209    virtual bool checkMnemonic(const CString& mnemonic) const = 0;
210    /// set allocated registers (if regs is null then reset them)
211    virtual void setAllocatedRegisters(const cxuint* regs = nullptr,
212                Flags regFlags = 0) = 0;
213    /// get allocated register numbers after assemblying
214    virtual const cxuint* getAllocatedRegisters(size_t& regTypesNum,
215                Flags& regFlags) const = 0;
216    /// get max registers number
217    virtual void getMaxRegistersNum(size_t& regTypesNum, cxuint* maxRegs) const = 0;
218    /// get registers ranges
219    virtual void getRegisterRanges(size_t& regTypesNum, cxuint* regRanges) const = 0;
220    /// fill alignment when value is not given
221    virtual void fillAlignment(size_t size, cxbyte* output) = 0;
222    /// parse register range
223    virtual bool parseRegisterRange(const char*& linePtr, cxuint& regStart,
224                        cxuint& regEnd, const AsmRegVar*& regVar) = 0;
225    /// return true if expresion of target fit to value with specified bits
226    virtual bool relocationIsFit(cxuint bits, AsmExprTargetType tgtType) = 0;
227    /// parse register type for '.reg' pseudo-op
228    virtual bool parseRegisterType(const char*& linePtr,
229                       const char* end, cxuint& type) = 0;
230    /// get size of instruction
231    virtual size_t getInstructionSize(size_t codeSize, const cxbyte* code) const = 0;
232};
233
234/// GCN arch assembler
235class GCNAssembler: public ISAAssembler
236{
237public:
238    /// register pool numbers
239    struct Regs {
240        cxuint sgprsNum;    ///< SGPRs number
241        cxuint vgprsNum;    ///< VGPRs number
242        Flags regFlags; ///< define what extra register must be included
243    };
244private:
245    friend struct GCNAsmUtils; // INTERNAL LOGIC
246    union {
247        Regs regs;
248        cxuint regTable[2];
249    };
250    uint16_t curArchMask;
251    cxbyte currentRVUIndex;
252    AsmRegVarUsage instrRVUs[6];
253   
254    void resetInstrRVUs()
255    {
256        for (AsmRegVarUsage& rvu: instrRVUs)
257            rvu.regField = ASMFIELD_NONE;
258    }
259    void setCurrentRVU(cxbyte idx)
260    { currentRVUIndex = idx; }
261   
262    void setRegVarUsage(const AsmRegVarUsage& rvu)
263    { instrRVUs[currentRVUIndex] = rvu; }
264   
265    void flushInstrRVUs(ISAUsageHandler* usageHandler)
266    {
267        for (const AsmRegVarUsage& rvu: instrRVUs)
268            if (rvu.regField != ASMFIELD_NONE)
269                usageHandler->pushUsage(rvu);
270    }
271public:
272    /// constructor
273    explicit GCNAssembler(Assembler& assembler);
274    /// destructor
275    ~GCNAssembler();
276   
277    ISAUsageHandler* createUsageHandler(std::vector<cxbyte>& content) const;
278   
279    void assemble(const CString& mnemonic, const char* mnemPlace, const char* linePtr,
280                  const char* lineEnd, std::vector<cxbyte>& output,
281                  ISAUsageHandler* usageHandler);
282    bool resolveCode(const AsmSourcePos& sourcePos, cxuint targetSectionId,
283                 cxbyte* sectionData, size_t offset, AsmExprTargetType targetType,
284                 cxuint sectionId, uint64_t value);
285    bool checkMnemonic(const CString& mnemonic) const;
286    void setAllocatedRegisters(const cxuint* regs, Flags regFlags);
287    const cxuint* getAllocatedRegisters(size_t& regTypesNum, Flags& regFlags) const;
288    void getMaxRegistersNum(size_t& regTypesNum, cxuint* maxRegs) const;
289    void getRegisterRanges(size_t& regTypesNum, cxuint* regRanges) const;
290    void fillAlignment(size_t size, cxbyte* output);
291    bool parseRegisterRange(const char*& linePtr, cxuint& regStart, cxuint& regEnd,
292                const AsmRegVar*& regVar);
293    bool relocationIsFit(cxuint bits, AsmExprTargetType tgtType);
294    bool parseRegisterType(const char*& linePtr, const char* end, cxuint& type);
295    size_t getInstructionSize(size_t codeSize, const cxbyte* code) const;
296};
297
298class AsmRegAllocator
299{
300public:
301    struct NextBlock
302    {
303        size_t block;
304        bool isCall;
305    };
306    struct SSAInfo
307    {
308        size_t ssaIdBefore; ///< SSA id before first SSA in block
309        size_t ssaIdFirst; // SSA id at first change
310        size_t ssaId;   ///< original SSA id
311        size_t ssaIdLast; ///< last SSA id in last
312        size_t ssaIdChange; ///< number of SSA id changes
313        size_t firstPos;
314        size_t lastPos;
315        bool readBeforeWrite;   ///< have read before write
316        SSAInfo(size_t _bssaId = SIZE_MAX, size_t _ssaIdF = SIZE_MAX,
317                size_t _ssaId = SIZE_MAX, size_t _ssaIdL = SIZE_MAX,
318                size_t _ssaIdChange = 0, bool _readBeforeWrite = false)
319            : ssaIdBefore(_bssaId), ssaIdFirst(_ssaIdF), ssaId(_ssaId),
320              ssaIdLast(_ssaIdL), ssaIdChange(_ssaIdChange),
321              readBeforeWrite(_readBeforeWrite)
322        { }
323    };
324    struct CodeBlock
325    {
326        size_t start, end; // place in code
327        std::vector<NextBlock> nexts; ///< nexts blocks, if empty then direct next block
328        bool haveCalls;
329        bool haveReturn;
330        bool haveEnd;
331        // key - regvar, value - SSA info for this regvar
332        std::unordered_map<AsmSingleVReg, SSAInfo> ssaInfoMap;
333        ISAUsageHandler::ReadPos usagePos;
334    };
335   
336     // first - orig ssaid, second - dest ssaid
337    typedef std::pair<size_t, size_t> SSAReplace;
338    typedef std::unordered_map<AsmSingleVReg, std::vector<SSAReplace> > SSAReplacesMap;
339    // interference graph type
340    typedef Array<std::unordered_set<size_t> > InterGraph;
341    typedef std::unordered_map<AsmSingleVReg, std::vector<size_t> > VarIndexMap;
342    struct LinearDep
343    {
344        cxbyte align;
345        std::vector<size_t> prevVidxes;
346        std::vector<size_t> nextVidxes;
347    };
348    struct EqualToDep
349    {
350        std::vector<size_t> prevVidxes;
351        std::vector<size_t> nextVidxes;
352    };
353private:
354    Assembler& assembler;
355    std::vector<CodeBlock> codeBlocks;
356    SSAReplacesMap ssaReplacesMap;
357    size_t regTypesNum;
358   
359    VarIndexMap vregIndexMaps[MAX_REGTYPES_NUM]; // indices to igraph for 2 reg types
360    InterGraph interGraphs[MAX_REGTYPES_NUM]; // for 2 register
361    Array<cxuint> graphColorMaps[MAX_REGTYPES_NUM];
362    std::unordered_map<size_t, LinearDep> linearDepMaps[MAX_REGTYPES_NUM];
363    std::unordered_map<size_t, EqualToDep> equalToDepMaps[MAX_REGTYPES_NUM];
364    std::unordered_map<size_t, size_t> equalSetMaps[MAX_REGTYPES_NUM];
365    std::vector<std::vector<size_t> > equalSetLists[MAX_REGTYPES_NUM];
366public:
367    AsmRegAllocator(Assembler& assembler);
368   
369    void createCodeStructure(const std::vector<AsmCodeFlowEntry>& codeFlow,
370             size_t codeSize, const cxbyte* code);
371    void createSSAData(ISAUsageHandler& usageHandler);
372    void applySSAReplaces();
373    void createInterferenceGraph(ISAUsageHandler& usageHandler);
374    void colorInterferenceGraph();
375   
376    void allocateRegisters(cxuint sectionId);
377   
378    const std::vector<CodeBlock>& getCodeBlocks() const
379    { return codeBlocks; }
380    const SSAReplacesMap& getSSAReplacesMap() const
381    { return ssaReplacesMap; }
382};
383
384/// type of clause
385enum class AsmClauseType
386{
387    IF,     ///< if clause
388    ELSEIF, ///< elseif clause
389    ELSE,   ///< else clause
390    REPEAT, ///< rept clause or irp/irpc clause
391    MACRO   ///< macro clause
392};
393
394/// assembler's clause (if,else,macro,rept)
395struct AsmClause
396{
397    AsmClauseType type; ///< type of clause
398    AsmSourcePos sourcePos;   ///< position in source code
399    bool condSatisfied; ///< if conditional clause has already been satisfied
400    AsmSourcePos prevIfPos; ///< position of previous if-clause
401};
402
403/// main class of assembler
404class Assembler: public NonCopyableAndNonMovable
405{
406public:
407    /// defined symbol entry
408    typedef std::pair<CString, uint64_t> DefSym;
409    /// kernel map type
410    typedef std::unordered_map<CString, cxuint> KernelMap;
411private:
412    friend class AsmStreamInputFilter;
413    friend class AsmMacroInputFilter;
414    friend class AsmForInputFilter;
415    friend class AsmExpression;
416    friend class AsmFormatHandler;
417    friend class AsmRawCodeHandler;
418    friend class AsmAmdHandler;
419    friend class AsmAmdCL2Handler;
420    friend class AsmGalliumHandler;
421    friend class AsmROCmHandler;
422    friend class ISAAssembler;
423    friend class AsmRegAllocator;
424   
425    friend struct AsmParseUtils; // INTERNAL LOGIC
426    friend struct AsmPseudoOps; // INTERNAL LOGIC
427    friend struct AsmGalliumPseudoOps; // INTERNAL LOGIC
428    friend struct AsmAmdPseudoOps; // INTERNAL LOGIC
429    friend struct AsmAmdCL2PseudoOps; // INTERNAL LOGIC
430    friend struct AsmROCmPseudoOps; // INTERNAL LOGIC
431    friend struct GCNAsmUtils; // INTERNAL LOGIC
432
433    Array<CString> filenames;
434    BinaryFormat format;
435    GPUDeviceType deviceType;
436    uint32_t driverVersion;
437    uint32_t llvmVersion; // GalliumCompute
438    bool _64bit;    ///
439    bool newROCmBinFormat;
440    bool good;
441    bool resolvingRelocs;
442    bool doNotRemoveFromSymbolClones;
443    ISAAssembler* isaAssembler;
444    std::vector<DefSym> defSyms;
445    std::vector<CString> includeDirs;
446    std::vector<AsmSection> sections;
447    std::vector<Array<cxuint> > relSpacesSections;
448    std::unordered_set<AsmSymbolEntry*> symbolSnapshots;
449    std::unordered_set<AsmSymbolEntry*> symbolClones;
450    std::vector<AsmExpression*> unevalExpressions;
451    std::vector<AsmRelocation> relocations;
452    AsmScope globalScope;
453    AsmMacroMap macroMap;
454    std::stack<AsmScope*> scopeStack;
455    std::vector<AsmScope*> abandonedScopes;
456    AsmScope* currentScope;
457    KernelMap kernelMap;
458    std::vector<AsmKernel> kernels;
459    /// register variables
460    Flags flags;
461    uint64_t macroCount;
462    uint64_t localCount; // macro's local count
463    bool alternateMacro;
464    bool buggyFPLit;
465    bool macroCase;
466    bool oldModParam;
467   
468    cxuint inclusionLevel;
469    cxuint macroSubstLevel;
470    cxuint repetitionLevel;
471    bool lineAlreadyRead; // if line already read
472   
473    size_t lineSize;
474    const char* line;
475    bool endOfAssembly;
476    bool sectionDiffsPrepared;
477   
478    cxuint filenameIndex;
479    std::stack<AsmInputFilter*> asmInputFilters;
480    AsmInputFilter* currentInputFilter;
481   
482    std::ostream& messageStream;
483    std::ostream& printStream;
484   
485    AsmFormatHandler* formatHandler;
486   
487    std::stack<AsmClause> clauses;
488   
489    cxuint currentKernel;
490    cxuint& currentSection;
491    uint64_t& currentOutPos;
492   
493    bool withSectionDiffs() const
494    { return formatHandler!=nullptr && formatHandler->isSectionDiffsResolvable(); }
495   
496    AsmSourcePos getSourcePos(LineCol lineCol) const
497    {
498        return { currentInputFilter->getMacroSubst(), currentInputFilter->getSource(),
499            lineCol.lineNo, lineCol.colNo };
500    }
501   
502    AsmSourcePos getSourcePos(size_t pos) const
503    { return currentInputFilter->getSourcePos(pos); }
504    AsmSourcePos getSourcePos(const char* linePtr) const
505    { return getSourcePos(linePtr-line); }
506   
507    void printWarning(const AsmSourcePos& pos, const char* message);
508    void printError(const AsmSourcePos& pos, const char* message);
509   
510    void printWarning(const char* linePtr, const char* message)
511    { printWarning(getSourcePos(linePtr), message); }
512    void printError(const char* linePtr, const char* message)
513    { printError(getSourcePos(linePtr), message); }
514   
515    void printWarning(LineCol lineCol, const char* message)
516    { printWarning(getSourcePos(lineCol), message); }
517    void printError(LineCol lineCol, const char* message)
518    { printError(getSourcePos(lineCol), message); }
519   
520    LineCol translatePos(const char* linePtr) const
521    { return currentInputFilter->translatePos(linePtr-line); }
522    LineCol translatePos(size_t pos) const
523    { return currentInputFilter->translatePos(pos); }
524   
525    bool parseLiteral(uint64_t& value, const char*& linePtr);
526    bool parseLiteralNoError(uint64_t& value, const char*& linePtr);
527    bool parseString(std::string& outString, const char*& linePtr);
528   
529    enum class ParseState
530    {
531        FAILED = 0,
532        PARSED,
533        MISSING // missing element
534    };
535   
536    /** parse symbol
537     * \return state
538     */
539    ParseState parseSymbol(const char*& linePtr, AsmSymbolEntry*& entry,
540                   bool localLabel = true, bool dontCreateSymbol = false);
541    bool skipSymbol(const char*& linePtr);
542   
543    bool setSymbol(AsmSymbolEntry& symEntry, uint64_t value, cxuint sectionId);
544   
545    bool assignSymbol(const CString& symbolName, const char* symbolPlace,
546                  const char* linePtr, bool reassign = true, bool baseExpr = false);
547   
548    bool assignOutputCounter(const char* symbolPlace, uint64_t value, cxuint sectionId,
549                     cxbyte fillValue = 0);
550   
551    void parsePseudoOps(const CString& firstName, const char* stmtPlace,
552                const char* linePtr);
553   
554    /// exitm - exit macro mode
555    bool skipClauses(bool exitm = false);
556    bool putMacroContent(RefPtr<AsmMacro> macro);
557    bool putRepetitionContent(AsmRepeat& repeat);
558   
559    void initializeOutputFormat();
560   
561    bool pushClause(const char* string, AsmClauseType clauseType)
562    {
563        bool included; // to ignore
564        return pushClause(string, clauseType, true, included);
565    }
566    bool pushClause(const char* string, AsmClauseType clauseType,
567                  bool satisfied, bool& included);
568     // return false when failed (for example no clauses)
569    bool popClause(const char* string, AsmClauseType clauseType);
570   
571    // recursive function to find scope in scope
572    AsmScope* findScopeInScope(AsmScope* scope, const CString& scopeName,
573                    std::unordered_set<AsmScope*>& scopeSet);
574    // find scope by identifier
575    AsmScope* getRecurScope(const CString& scopePlace, bool ignoreLast = false,
576                    const char** lastStep = nullptr);
577    // find symbol in scopes
578    // internal recursive function to find symbol in scope
579    AsmSymbolEntry* findSymbolInScopeInt(AsmScope* scope, const CString& symName,
580                    std::unordered_set<AsmScope*>& scopeSet);
581    // scope - return scope from scoped name
582    AsmSymbolEntry* findSymbolInScope(const CString& symName, AsmScope*& scope,
583                      CString& sameSymName, bool insertMode = false);
584    // similar to map::insert, but returns pointer
585    std::pair<AsmSymbolEntry*, bool> insertSymbolInScope(const CString& symName,
586                 const AsmSymbol& symbol);
587   
588    // internal recursive function to find symbol in scope
589    AsmRegVarEntry* findRegVarInScopeInt(AsmScope* scope, const CString& rvName,
590                    std::unordered_set<AsmScope*>& scopeSet);
591    // scope - return scope from scoped name
592    AsmRegVarEntry* findRegVarInScope(const CString& rvName, AsmScope*& scope,
593                      CString& sameRvName, bool insertMode = false);
594    // similar to map::insert, but returns pointer
595    std::pair<AsmRegVarEntry*, bool> insertRegVarInScope(const CString& rvName,
596                 const AsmRegVar& regVar);
597   
598    // create scope
599    bool getScope(AsmScope* parent, const CString& scopeName, AsmScope*& scope);
600    // push new scope level
601    bool pushScope(const CString& scopeName);
602    bool popScope();
603   
604    /// returns false when includeLevel is too deep, throw error if failed a file opening
605    bool includeFile(const char* pseudoOpPlace, const std::string& filename);
606   
607    ParseState makeMacroSubstitution(const char* string);
608   
609    bool parseMacroArgValue(const char*& linePtr, std::string& outStr);
610   
611    void putData(size_t size, const cxbyte* data)
612    {
613        AsmSection& section = sections[currentSection];
614        section.content.insert(section.content.end(), data, data+size);
615        currentOutPos += size;
616    }
617   
618    cxbyte* reserveData(size_t size, cxbyte fillValue = 0);
619   
620    void goToMain(const char* pseudoOpPlace);
621    void goToKernel(const char* pseudoOpPlace, const char* kernelName);
622    void goToSection(const char* pseudoOpPlace, const char* sectionName, uint64_t align=0);
623    void goToSection(const char* pseudoOpPlace, const char* sectionName,
624                     AsmSectionType type, Flags flags, uint64_t align=0);
625    void goToSection(const char* pseudoOpPlace, cxuint sectionId, uint64_t align=0);
626   
627    void printWarningForRange(cxuint bits, uint64_t value, const AsmSourcePos& pos,
628                  cxbyte signess = WS_BOTH);
629   
630    bool isAddressableSection() const
631    {
632        return currentSection==ASMSECT_ABS ||
633                    (sections[currentSection].flags & ASMSECT_ADDRESSABLE) != 0;
634    }
635    bool isWriteableSection() const
636    {
637        return currentSection!=ASMSECT_ABS &&
638                (sections[currentSection].flags & ASMSECT_WRITEABLE) != 0;
639    }
640    bool isResolvableSection() const
641    {
642        return currentSection==ASMSECT_ABS ||
643                (sections[currentSection].flags & ASMSECT_UNRESOLVABLE) == 0;
644    }
645    bool isResolvableSection(cxuint sectionId) const
646    {
647        return sectionId==ASMSECT_ABS ||
648                (sections[sectionId].flags & ASMSECT_UNRESOLVABLE) == 0;
649    }
650   
651    // oldKernels and newKernels must be sorted
652    void handleRegionsOnKernels(const std::vector<cxuint>& newKernels,
653                const std::vector<cxuint>& oldKernels, cxuint codeSection);
654   
655    void tryToResolveSymbol(AsmSymbolEntry& symEntry);
656    void tryToResolveSymbols(AsmScope* scope);
657    void printUnresolvedSymbols(AsmScope* scope);
658   
659    bool resolveExprTarget(const AsmExpression* expr, uint64_t value, cxuint sectionId);
660   
661    void cloneSymEntryIfNeeded(AsmSymbolEntry& symEntry);
662   
663    void undefineSymbol(AsmSymbolEntry& symEntry);
664   
665protected:
666    /// helper for testing
667    bool readLine();
668public:
669    /// constructor with filename and input stream
670    /**
671     * \param filename filename
672     * \param input input stream
673     * \param flags assembler flags
674     * \param format output format type
675     * \param deviceType GPU device type
676     * \param msgStream stream for warnings and errors
677     * \param printStream stream for printing message by .print pseudo-ops
678     */
679    explicit Assembler(const CString& filename, std::istream& input, Flags flags = 0,
680              BinaryFormat format = BinaryFormat::AMD,
681              GPUDeviceType deviceType = GPUDeviceType::CAPE_VERDE,
682              std::ostream& msgStream = std::cerr, std::ostream& printStream = std::cout);
683   
684    /// constructor with filename and input stream
685    /**
686     * \param filenames filenames
687     * \param flags assembler flags
688     * \param format output format type
689     * \param deviceType GPU device type
690     * \param msgStream stream for warnings and errors
691     * \param printStream stream for printing message by .print pseudo-ops
692     */
693    explicit Assembler(const Array<CString>& filenames, Flags flags = 0,
694              BinaryFormat format = BinaryFormat::AMD,
695              GPUDeviceType deviceType = GPUDeviceType::CAPE_VERDE,
696              std::ostream& msgStream = std::cerr, std::ostream& printStream = std::cout);
697    /// destructor
698    ~Assembler();
699   
700    /// main routine to assemble code
701    bool assemble();
702   
703    /// write binary to file
704    void writeBinary(const char* filename) const;
705    /// write binary to stream
706    void writeBinary(std::ostream& outStream) const;
707    /// write binary to array
708    void writeBinary(Array<cxbyte>& array) const;
709   
710    /// get AMD driver version
711    uint32_t getDriverVersion() const
712    { return driverVersion; }
713    /// set AMD driver version
714    void setDriverVersion(uint32_t driverVersion)
715    { this->driverVersion = driverVersion; }
716   
717    /// get LLVM version
718    uint32_t getLLVMVersion() const
719    { return llvmVersion; }
720    /// set LLVM version
721    void setLLVMVersion(uint32_t llvmVersion)
722    { this->llvmVersion = llvmVersion; }
723   
724    /// get GPU device type
725    GPUDeviceType getDeviceType() const
726    { return deviceType; }
727    /// set GPU device type
728    void setDeviceType(const GPUDeviceType deviceType)
729    { this->deviceType = deviceType; }
730    /// get binary format
731    BinaryFormat getBinaryFormat() const
732    { return format; }
733    /// set binary format
734    void setBinaryFormat(BinaryFormat binFormat)
735    { format = binFormat; }
736    /// get bitness (true if 64-bit)
737    bool is64Bit() const
738    { return _64bit; }
739    /// set bitness (true if 64-bit)
740    void set64Bit(bool this64Bit)
741    {  _64bit = this64Bit; }
742    /// is new ROCm binary format
743    bool isNewROCmBinFormat() const
744    { return newROCmBinFormat; }
745    /// set new ROCm binary format
746    void setNewROCmBinFormat(bool newFmt)
747    { newROCmBinFormat = newFmt; }
748    /// get flags
749    Flags getFlags() const
750    { return flags; }
751    /// set flags
752    void setFlags(Flags flags)
753    { this->flags = flags; }
754    /// get true if altMacro enabled
755    bool isAltMacro() const
756    { return alternateMacro; }
757    /// get true if macroCase enabled
758    bool isMacroCase() const
759    { return macroCase; }
760    /// get true if oldModParam enabled (old modifier parametrization)
761    bool isOldModParam() const
762    { return oldModParam; }
763    /// get true if buggyFPLit enabled
764    bool isBuggyFPLit() const
765    { return buggyFPLit; }
766    /// get include directory list
767    const std::vector<CString>& getIncludeDirs() const
768    { return includeDirs; }
769    /// adds include directory
770    void addIncludeDir(const CString& includeDir);
771    /// get symbols map
772    const AsmSymbolMap& getSymbolMap() const
773    { return globalScope.symbolMap; }
774    /// get sections
775    const std::vector<AsmSection>& getSections() const
776    { return sections; }
777    // get first sections for rel spaces
778    const std::vector<Array<cxuint> >& getRelSpacesSections() const
779    { return relSpacesSections; }
780    /// get kernel map
781    const KernelMap& getKernelMap() const
782    { return kernelMap; }
783    /// get kernels
784    const std::vector<AsmKernel>& getKernels() const
785    { return kernels; }
786    /// get regvar map
787    const AsmRegVarMap& getRegVarMap() const
788    { return globalScope.regVarMap; }
789    /// add regvar
790    bool addRegVar(const CString& name, const AsmRegVar& var)
791    { return insertRegVarInScope(name, var).second; }
792    /// get regvar by name
793    bool getRegVar(const CString& name, const AsmRegVar*& regVar);
794   
795    /// get global scope
796    const AsmScope& getGlobalScope() const
797    { return globalScope; }
798   
799    /// returns true if symbol contains absolute value
800    bool isAbsoluteSymbol(const AsmSymbol& symbol) const;
801   
802    /// add initiali defsyms
803    void addInitialDefSym(const CString& symName, uint64_t value);
804   
805    /// get format handler
806    const AsmFormatHandler* getFormatHandler() const
807    { return formatHandler; }
808};
809
810inline void ISAAssembler::printWarning(const char* linePtr, const char* message)
811{ assembler.printWarning(linePtr, message); }
812
813inline void ISAAssembler::printError(const char* linePtr, const char* message)
814{ assembler.printError(linePtr, message); }
815
816inline void ISAAssembler::printWarningForRange(cxuint bits, uint64_t value,
817                   const AsmSourcePos& pos, cxbyte signess)
818{ assembler.printWarningForRange(bits, value, pos, signess); }
819
820inline void ISAAssembler::printWarning(const AsmSourcePos& sourcePos, const char* message)
821{ assembler.printWarning(sourcePos, message); }
822
823inline void ISAAssembler::printError(const AsmSourcePos& sourcePos, const char* message)
824{ assembler.printError(sourcePos, message); }
825
826inline void ISAAssembler::addCodeFlowEntry(cxuint sectionId, const AsmCodeFlowEntry& entry)
827{ assembler.sections[sectionId].addCodeFlowEntry(entry); }
828
829};
830
831#endif
Note: See TracBrowser for help on using the repository browser.