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

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

CLRadeonExtender: Comment typo in AsmGalliumFormat?. Code for AsmROCmFormat.
ROCmBinGen: Add addEmptyKernel to ROCmInput.

File size: 33.3 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/*! \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 <unordered_set>
36#include <unordered_map>
37#include <CLRX/utils/Utilities.h>
38#include <CLRX/amdasm/Commons.h>
39#include <CLRX/amdasm/AsmSource.h>
40#include <CLRX/amdasm/AsmFormats.h>
41
42/// main namespace
43namespace CLRX
44{
45
46enum: Flags
47{
48    ASM_WARNINGS = 1,   ///< enable all warnings for assembler
49    ASM_FORCE_ADD_SYMBOLS = 2,
50    ASM_ALTMACRO = 4,
51    ASM_BUGGYFPLIT = 8, // buggy handling of fpliterals (including fp constants)
52    ASM_TESTRUN = (1U<<31), ///< only for running tests
53    ASM_ALL = FLAGS_ALL&~(ASM_TESTRUN|ASM_BUGGYFPLIT)  ///< all flags
54};
55
56enum: cxbyte {
57    WS_UNSIGNED = 0,  // only unsigned
58    WS_BOTH = 1,  // both signed and unsigned range checking
59};
60
61/// expression target type (one byte)
62typedef cxbyte AsmExprTargetType;
63
64enum : AsmExprTargetType
65{
66    ASMXTGT_SYMBOL = 0, ///< target is symbol
67    ASMXTGT_DATA8,      ///< target is byte
68    ASMXTGT_DATA16,     ///< target is 16-bit word
69    ASMXTGT_DATA32,     ///< target is 32-bit word
70    ASMXTGT_DATA64,     ///< target is 64-bit word
71   
72    GCNTGT_LITIMM = 16,
73    GCNTGT_SOPKSIMM16,
74    GCNTGT_SOPJMP,
75    GCNTGT_SMRDOFFSET,
76    GCNTGT_DSOFFSET16,
77    GCNTGT_DSOFFSET8_0,
78    GCNTGT_DSOFFSET8_1,
79    GCNTGT_MXBUFOFFSET,
80    GCNTGT_SMEMOFFSET,
81    GCNTGT_SOPCIMM8,
82    GCNTGT_SMEMIMM
83};
84
85struct AsmRegVar;
86
87/// ISA assembler class
88class ISAAssembler: public NonCopyableAndNonMovable
89{
90protected:
91    Assembler& assembler;       ///< assembler
92   
93    /// print warning for position pointed by line pointer
94    void printWarning(const char* linePtr, const char* message);
95    /// print error for position pointed by line pointer
96    void printError(const char* linePtr, const char* message);
97    /// print warning for source position
98    void printWarning(const AsmSourcePos& sourcePos, const char* message);
99    /// print error for source position
100    void printError(const AsmSourcePos& sourcePos, const char* message);
101    /// print warning about integer out of range
102    void printWarningForRange(cxuint bits, uint64_t value, const AsmSourcePos& pos,
103                cxbyte signess = WS_BOTH);
104    /// constructor
105    explicit ISAAssembler(Assembler& assembler);
106public:
107    /// destructor
108    virtual ~ISAAssembler();
109   
110    /// assemble single line
111    virtual void assemble(const CString& mnemonic, const char* mnemPlace,
112              const char* linePtr, const char* lineEnd, std::vector<cxbyte>& output) = 0;
113    /// resolve code with location, target and value
114    virtual bool resolveCode(const AsmSourcePos& sourcePos, cxuint targetSectionId,
115                 cxbyte* sectionData, size_t offset, AsmExprTargetType targetType,
116                 cxuint sectionId, uint64_t value) = 0;
117    /// check if name is mnemonic
118    virtual bool checkMnemonic(const CString& mnemonic) const = 0;
119    /// set allocated registers (if regs is null then reset them)
120    virtual void setAllocatedRegisters(const cxuint* regs = nullptr,
121                Flags regFlags = 0) = 0;
122    /// get allocated register numbers after assemblying
123    virtual const cxuint* getAllocatedRegisters(size_t& regTypesNum,
124                Flags& regFlags) const = 0;
125    /// fill alignment when value is not given
126    virtual void fillAlignment(size_t size, cxbyte* output) = 0;
127    /// parse register range
128    virtual bool parseRegisterRange(const char*& linePtr, cxuint& regStart,
129                        cxuint& regEnd, const AsmRegVar*& regVar) = 0;
130    /// return true if expresion of target fit to value with specified bits
131    virtual bool relocationIsFit(cxuint bits, AsmExprTargetType tgtType) = 0;
132    /// parse register type for '.reg' pseudo-op
133    virtual bool parseRegisterType(const char*& linePtr,
134                       const char* end, cxuint& type) = 0;
135};
136
137/// GCN arch assembler
138class GCNAssembler: public ISAAssembler
139{
140public:
141    /// register pool numbers
142    struct Regs {
143        cxuint sgprsNum;    ///< SGPRs number
144        cxuint vgprsNum;    ///< VGPRs number
145        Flags regFlags; ///< define what extra register must be included
146    };
147private:
148    union {
149        Regs regs;
150        cxuint regTable[2];
151    };
152    uint16_t curArchMask;
153public:
154    /// constructor
155    explicit GCNAssembler(Assembler& assembler);
156    /// destructor
157    ~GCNAssembler();
158   
159    void assemble(const CString& mnemonic, const char* mnemPlace, const char* linePtr,
160                  const char* lineEnd, std::vector<cxbyte>& output);
161    bool resolveCode(const AsmSourcePos& sourcePos, cxuint targetSectionId,
162                 cxbyte* sectionData, size_t offset, AsmExprTargetType targetType,
163                 cxuint sectionId, uint64_t value);
164    bool checkMnemonic(const CString& mnemonic) const;
165    void setAllocatedRegisters(const cxuint* regs, Flags regFlags);
166    const cxuint* getAllocatedRegisters(size_t& regTypesNum, Flags& regFlags) const;
167    void fillAlignment(size_t size, cxbyte* output);
168    bool parseRegisterRange(const char*& linePtr, cxuint& regStart, cxuint& regEnd,
169                const AsmRegVar*& regVar);
170    bool relocationIsFit(cxuint bits, AsmExprTargetType tgtType);
171    bool parseRegisterType(const char*& linePtr, const char* end, cxuint& type);
172};
173
174/*
175 * assembler expressions
176 */
177
178/// assembler expression operator
179enum class AsmExprOp : cxbyte
180{
181    ARG_VALUE = 0,  ///< absolute value
182    ARG_SYMBOL = 1,  ///< absolute symbol without defined value
183    NEGATE = 2, ///< negation
184    BIT_NOT,    ///< binary negation
185    LOGICAL_NOT,    ///< logical negation
186    PLUS,   ///< plus (nothing)
187    ADDITION,   ///< addition
188    SUBTRACT,       ///< subtraction
189    MULTIPLY,       ///< multiplication
190    DIVISION,       ///< unsigned division
191    SIGNED_DIVISION,    ///< signed division
192    MODULO,         ///< unsigned modulo
193    SIGNED_MODULO,      ///< signed modulo
194    BIT_AND,        ///< bitwise AND
195    BIT_OR,         //< bitwise OR
196    BIT_XOR,        ///< bitwise XOR
197    BIT_ORNOT,      ///< bitwise OR-not
198    SHIFT_LEFT,     ///< shift left
199    SHIFT_RIGHT,    ///< logical shift irght
200    SIGNED_SHIFT_RIGHT, ///< signed (arithmetic) shift right
201    LOGICAL_AND,    ///< logical AND
202    LOGICAL_OR,     ///< logical OR
203    EQUAL,          ///< equality
204    NOT_EQUAL,      ///< unequality
205    LESS,           ///< less than
206    LESS_EQ,        ///< less or equal than
207    GREATER,        ///< greater than
208    GREATER_EQ,     ///< greater or equal than
209    BELOW, ///< unsigned less
210    BELOW_EQ, ///< unsigned less or equal
211    ABOVE, ///< unsigned less
212    ABOVE_EQ, ///< unsigned less or equal
213    CHOICE,  ///< a ? b : c
214    CHOICE_START,   ///< helper
215    FIRST_ARG = ARG_VALUE,
216    LAST_ARG = ARG_SYMBOL,
217    FIRST_UNARY = NEGATE,   ///< helper
218    LAST_UNARY = PLUS,  ///< helper
219    FIRST_BINARY = ADDITION,    ///< helper
220    LAST_BINARY = ABOVE_EQ, ///< helper
221    NONE = 0xff ///< none operation
222};
223
224struct AsmExprTarget;
225
226union AsmExprArg;
227
228class AsmExpression;
229
230/// assembler symbol occurrence in expression
231struct AsmExprSymbolOccurrence
232{
233    AsmExpression* expression;      ///< target expression pointer
234    size_t argIndex;        ///< argument index
235    size_t opIndex;         ///< operator index
236   
237    /// comparison operator
238    bool operator==(const AsmExprSymbolOccurrence& b) const
239    { return expression==b.expression && opIndex==b.opIndex && argIndex==b.argIndex; }
240};
241
242struct AsmRegVar;
243
244/// assembler symbol structure
245struct AsmSymbol
246{
247    cxuint refCount;    ///< reference counter (for internal use only)
248    cxuint sectionId;       ///< section id
249    cxbyte info;           ///< ELF symbol info
250    cxbyte other;           ///< ELF symbol other
251    cxuint hasValue:1;         ///< symbol is defined
252    cxuint onceDefined:1;       ///< symbol can be only once defined (likes labels)
253    cxuint resolving:1;         ///< helper
254    cxuint base:1;              ///< with base expression
255    cxuint snapshot:1;          ///< if symbol is snapshot
256    cxuint regRange:1;          ///< if symbol is register range
257    uint64_t value;         ///< value of symbol
258    uint64_t size;          ///< size of symbol
259    union {
260        AsmExpression* expression;      ///< expression of symbol (if not resolved)
261        AsmRegVar* var;
262    };
263   
264    /** list of occurrences in expressions */
265    std::vector<AsmExprSymbolOccurrence> occurrencesInExprs;
266   
267    /// empty constructor
268    explicit AsmSymbol(bool _onceDefined = false) :
269            refCount(1), sectionId(ASMSECT_ABS), info(0), other(0), hasValue(false),
270            onceDefined(_onceDefined), resolving(false), base(false), snapshot(false),
271            regRange(false), value(0), size(0), expression(nullptr)
272    { }
273    /// constructor with expression
274    explicit AsmSymbol(AsmExpression* expr, bool _onceDefined = false, bool _base = false) :
275            refCount(1), sectionId(ASMSECT_ABS), info(0), other(0), hasValue(false),
276            onceDefined(_onceDefined), resolving(false), base(_base),
277            snapshot(false), regRange(false), value(0), size(0), expression(expr)
278    { }
279    /// constructor with value and section id
280    explicit AsmSymbol(cxuint _sectionId, uint64_t _value, bool _onceDefined = false) :
281            refCount(1), sectionId(_sectionId), info(0), other(0), hasValue(true),
282            onceDefined(_onceDefined), resolving(false), base(false), snapshot(false),
283            regRange(false), value(_value), size(0), expression(nullptr)
284    { }
285    /// destructor
286    ~AsmSymbol();
287   
288    /// adds occurrence in expression
289    void addOccurrenceInExpr(AsmExpression* expr, size_t argIndex, size_t opIndex)
290    { occurrencesInExprs.push_back({expr, argIndex, opIndex}); }
291    /// remove occurrence in expression
292    void removeOccurrenceInExpr(AsmExpression* expr, size_t argIndex, size_t opIndex);
293    /// clear list of occurrences in expression
294    void clearOccurrencesInExpr();
295    /// make symbol as undefined
296    void undefine();
297    /// return true if symbol defined (have value or expression)
298    bool isDefined() const
299    { return hasValue || expression!=nullptr; }
300};
301
302/// assembler symbol map
303typedef std::unordered_map<CString, AsmSymbol> AsmSymbolMap;
304/// assembler symbol entry
305typedef AsmSymbolMap::value_type AsmSymbolEntry;
306
307/// target for assembler expression
308struct AsmExprTarget
309{
310    AsmExprTargetType type;    ///< type of target
311    union
312    {
313        AsmSymbolEntry* symbol; ///< symbol entry (if ASMXTGT_SYMBOL)
314        struct {
315            cxuint sectionId;   ///< section id of destination
316            size_t offset;      ///< offset of destination
317        };
318    };
319    /// empty constructor
320    AsmExprTarget() { }
321   
322    /// constructor to create custom target
323    AsmExprTarget(AsmExprTargetType _type, cxuint _sectionId, size_t _offset)
324            : type(_type), sectionId(_sectionId), offset(_offset)
325    { }
326   
327    /// make symbol target for expression
328    static AsmExprTarget symbolTarget(AsmSymbolEntry* entry)
329    { 
330        AsmExprTarget target;
331        target.type = ASMXTGT_SYMBOL;
332        target.symbol = entry;
333        return target;
334    }
335   
336    /// make n-bit word target for expression
337    template<typename T>
338    static AsmExprTarget dataTarget(cxuint sectionId, size_t offset)
339    {
340        AsmExprTarget target;
341        target.type = (sizeof(T)==1) ? ASMXTGT_DATA8 : (sizeof(T)==2) ? ASMXTGT_DATA16 :
342                (sizeof(T)==4) ? ASMXTGT_DATA32 : ASMXTGT_DATA64;
343        target.sectionId = sectionId;
344        target.offset = offset;
345        return target;
346    }
347};
348
349/// assembler relocation
350struct AsmRelocation
351{
352    cxuint sectionId;   ///< section id where relocation is present
353    size_t offset;  ///< offset of relocation
354    RelocType type; ///< relocation type
355    union {
356        AsmSymbolEntry* symbol; ///< symbol
357        cxuint relSectionId;    ///< section for which relocation is defined
358    };
359    uint64_t addend;    ///< addend
360};
361
362/// assembler expression class
363class AsmExpression: public NonCopyableAndNonMovable
364{
365private:
366    class TempSymbolSnapshotMap;
367   
368    AsmExprTarget target;
369    AsmSourcePos sourcePos;
370    size_t symOccursNum;
371    bool relativeSymOccurs;
372    bool baseExpr;
373    Array<AsmExprOp> ops;
374    std::unique_ptr<LineCol[]> messagePositions;    ///< for every potential message
375    std::unique_ptr<AsmExprArg[]> args;
376   
377    AsmSourcePos getSourcePos(size_t msgPosIndex) const
378    {
379        AsmSourcePos pos = sourcePos;
380        pos.lineNo = messagePositions[msgPosIndex].lineNo;
381        pos.colNo = messagePositions[msgPosIndex].colNo;
382        return pos;
383    }
384   
385    static bool makeSymbolSnapshot(Assembler& assembler,
386               TempSymbolSnapshotMap* snapshotMap, const AsmSymbolEntry& symEntry,
387               AsmSymbolEntry*& outSymEntry, const AsmSourcePos* topParentSourcePos);
388   
389    AsmExpression();
390    void setParams(size_t symOccursNum, bool relativeSymOccurs,
391            size_t _opsNum, const AsmExprOp* ops, size_t opPosNum, const LineCol* opPos,
392            size_t argsNum, const AsmExprArg* args, bool baseExpr = false);
393public:
394    /// constructor of expression (helper)
395    AsmExpression(const AsmSourcePos& pos, size_t symOccursNum, bool relativeSymOccurs,
396            size_t opsNum, size_t opPosNum, size_t argsNum, bool baseExpr = false);
397    /// constructor of expression (helper)
398    AsmExpression(const AsmSourcePos& pos, size_t symOccursNum, bool relativeSymOccurs,
399              size_t opsNum, const AsmExprOp* ops, size_t opPosNum,
400              const LineCol* opPos, size_t argsNum, const AsmExprArg* args,
401              bool baseExpr = false);
402    /// destructor
403    ~AsmExpression();
404   
405    /// return true if expression is empty
406    bool isEmpty() const
407    { return ops.empty(); }
408
409    /// helper to create symbol snapshot. Creates initial expression for symbol snapshot
410    AsmExpression* createForSnapshot(const AsmSourcePos* exprSourcePos) const;
411   
412    /// set target of expression
413    void setTarget(AsmExprTarget _target)
414    { target = _target; }
415   
416    /// try to evaluate expression
417    /**
418     * \param assembler assembler instace
419     * \param value output value
420     * \param sectionId output section id
421     * \return true if evaluated
422     */
423    bool evaluate(Assembler& assembler, uint64_t& value, cxuint& sectionId) const
424    { return evaluate(assembler, 0, ops.size(), value, sectionId); }
425   
426    /// try to evaluate expression
427    /**
428     * \param assembler assembler instace
429     * \param value output value
430     * \param opStart start operand
431     * \param opEnd end operand
432     * \param sectionId output section id
433     * \return true if evaluated
434     */
435    bool evaluate(Assembler& assembler, size_t opStart, size_t opEnd,
436                  uint64_t& value, cxuint& sectionId) const;
437   
438    /// parse expression. By default, also gets values of symbol or  creates them
439    /** parse expresion from assembler's line string. Accepts empty expression.
440     * \param assembler assembler
441     * \param linePos position in line and output position in line
442     * \param makeBase do not evaluate resolved symbols, put them to expression
443     * \param dontResolveSymbolsLater do not resolve symbols later
444     * \return expression pointer
445     */
446    static AsmExpression* parse(Assembler& assembler, size_t& linePos,
447                    bool makeBase = false, bool dontResolveSymbolsLater = false);
448   
449    /// parse expression. By default, also gets values of symbol or  creates them
450    /** parse expresion from assembler's line string. Accepts empty expression.
451     * \param assembler assembler
452     * \param linePtr string at position in line (returns output line pointer)
453     * \param makeBase do not evaluate resolved symbols, put them to expression
454     * \param dontResolveSymbolsLater do not resolve symbols later
455     * \return expression pointer
456     */
457    static AsmExpression* parse(Assembler& assembler, const char*& linePtr,
458              bool makeBase = false, bool dontResolveSymbolsLater = false);
459   
460    /// return true if is argument op
461    static bool isArg(AsmExprOp op)
462    { return (AsmExprOp::FIRST_ARG <= op && op <= AsmExprOp::LAST_ARG); }
463    /// return true if is unary op
464    static bool isUnaryOp(AsmExprOp op)
465    { return (AsmExprOp::FIRST_UNARY <= op && op <= AsmExprOp::LAST_UNARY); }
466    /// return true if is binary op
467    static bool isBinaryOp(AsmExprOp op)
468    { return (AsmExprOp::FIRST_BINARY <= op && op <= AsmExprOp::LAST_BINARY); }
469    /// get targer of expression
470    const AsmExprTarget& getTarget() const
471    { return target; }
472    /// get number of symbol occurrences in expression
473    size_t getSymOccursNum() const
474    { return symOccursNum; }
475    /// get number of symbol occurrences in expression
476    size_t hasRelativeSymOccurs() const
477    { return relativeSymOccurs; }
478    /// unreference symbol occurrences in expression (used internally)
479    bool unrefSymOccursNum()
480    { return --symOccursNum!=0; }
481   
482    /// substitute occurrence in expression by value
483    void substituteOccurrence(AsmExprSymbolOccurrence occurrence, uint64_t value,
484                  cxuint sectionId = ASMSECT_ABS);
485    /// get operators list
486    const Array<AsmExprOp>& getOps() const
487    { return ops; }
488    /// get argument list
489    const AsmExprArg* getArgs() const
490    { return args.get(); }
491    /// get source position
492    const AsmSourcePos& getSourcePos() const
493    { return sourcePos; }
494   
495    size_t toTop(size_t opIndex) const;
496   
497    /// make symbol snapshot (required to implement .eqv pseudo-op)   
498    static bool makeSymbolSnapshot(Assembler& assembler, const AsmSymbolEntry& symEntry,
499               AsmSymbolEntry*& outSymEntry, const AsmSourcePos* parentExprSourcePos);
500};
501
502inline AsmSymbol::~AsmSymbol()
503{
504    if (base) delete expression; // if symbol with base expresion
505    clearOccurrencesInExpr();
506}
507
508/// assembler expression argument
509union AsmExprArg
510{
511    AsmSymbolEntry* symbol; ///< if symbol
512    uint64_t value;         ///< value
513    struct {
514        uint64_t value;         ///< value
515        cxuint sectionId;       ///< sectionId
516    } relValue; ///< relative value (with section)
517};
518
519inline void AsmExpression::substituteOccurrence(AsmExprSymbolOccurrence occurrence,
520                        uint64_t value, cxuint sectionId)
521{
522    ops[occurrence.opIndex] = AsmExprOp::ARG_VALUE;
523    args[occurrence.argIndex].relValue.value = value;
524    args[occurrence.argIndex].relValue.sectionId = sectionId;
525    if (sectionId != ASMSECT_ABS)
526        relativeSymOccurs = true;
527}
528
529typedef cxbyte AsmRegField;
530
531enum : AsmRegField
532{
533    GCNFIELD_SSRC0 = 0,
534    GCNFIELD_SSRC1,
535    GCNFIELD_SDST,
536    GCNFIELD_SMRD_SBASE,
537    GCNFIELD_SMRD_SDST,
538    GCNFIELD_SMRD_SOFFSET,
539    GCNFIELD_VOP_SRC0,
540    GCNFIELD_VOP_SRC1,
541    GCNFIELD_VOP_VDST,
542    GCNFIELD_VOP3_VSRC0,
543    GCNFIELD_VOP3_SRC1,
544    GCNFIELD_VOP3_VDST,
545    GCNFIELD_VOP3_SSRC,
546    GCNFIELD_VOP3_SDST,
547    GCNFIELD_VINTRP_VSRC0,
548    GCNFIELD_VINTRP_VDST,
549    GCNFIELD_DS_ADDR,
550    GCNFIELD_DS_DATA0,
551    GCNFIELD_DS_DATA1,
552    GCNFIELD_DS_VDST,
553    GCNFIELD_M_VADDR,
554    GCNFIELD_M_VDATA,
555    GCNFIELD_M_SRSRC,
556    GCNFIELD_MIMG_SSAMP,
557    GCNFIELD_M_SOFFSET,
558    GCNFIELD_EXP_VSRC0,
559    GCNFIELD_EXP_VSRC1,
560    GCNFIELD_EXP_VSRC2,
561    GCNFIELD_EXP_VSRC3,
562    GCNFIELD_FLAT_ADDR,
563    GCNFIELD_FLAT_DATA,
564    GCNFIELD_FLAT_VDST,
565    GCNFIELD_DPPSDWA_SRC0,
566    GCNFIELD_SMEM_SBASE,
567    GCNFIELD_SMEM_SDATA,
568    GCNFIELD_SMEM_OFFSET,
569    ASMFIELD_NONE = 255
570};
571
572enum : cxbyte
573{
574    GCNREGTYPE_SGPR,
575    GCNREGTYPE_VGPR
576};
577
578struct AsmRegVar
579{
580    cxuint type;    // scalar/vector/other
581    uint16_t size;  // in regs
582};
583
584struct AsmVarUsage
585{
586    size_t offset;
587    AsmRegField regField;   ///< place in instruction
588    uint16_t rstart, rend;
589    bool read;
590    bool write;
591    cxbyte align;   /// register alignment
592    const AsmRegVar* regVar;    // if null, then usage of called register
593};
594
595/// assembler section
596struct AsmSection
597{
598    const char* name;       ///< section name
599    cxuint kernelId;    ///< kernel id (optional)
600    AsmSectionType type;        ///< type of section
601    Flags flags;   ///< section flags
602    uint64_t alignment; ///< section alignment
603    uint64_t size;  ///< section size
604    std::vector<cxbyte> content;    ///< content of section
605   
606    /// register variables
607    std::unordered_map<CString, AsmRegVar> regVars;
608    /// reg-var usage in section
609    std::vector<AsmVarUsage> regVarUsages;
610   
611    bool addRegVar(const CString& name, const AsmRegVar& var);
612   
613    bool getRegVar(const CString& name, const AsmRegVar*& regVar) const;
614   
615    void addVarUsage(const AsmVarUsage& varUsage)
616    { regVarUsages.push_back(varUsage); }
617   
618    /// get section's size
619    size_t getSize() const
620    { return ((flags&ASMSECT_WRITEABLE) != 0) ? content.size() : size; }
621};
622
623/// type of clause
624enum class AsmClauseType
625{
626    IF,     ///< if clause
627    ELSEIF, ///< elseif clause
628    ELSE,   ///< else clause
629    REPEAT, ///< rept clause or irp/irpc clause
630    MACRO   ///< macro clause
631};
632
633/// kernel entry structure
634struct AsmKernel
635{
636    const char* name;   ///< name of kernel
637    AsmSourcePos sourcePos; ///< source position of definition
638};
639
640/// assembler's clause (if,else,macro,rept)
641struct AsmClause
642{
643    AsmClauseType type; ///< type of clause
644    AsmSourcePos sourcePos;   ///< position in source code
645    bool condSatisfied; ///< if conditional clause has already been satisfied
646    AsmSourcePos prevIfPos; ///< position of previous if-clause
647};
648
649/// main class of assembler
650class Assembler: public NonCopyableAndNonMovable
651{
652public:
653    /// defined symbol entry
654    typedef std::pair<CString, uint64_t> DefSym;
655    /// macro map type
656    typedef std::unordered_map<CString, RefPtr<const AsmMacro> > MacroMap;
657    /// kernel map type
658    typedef std::unordered_map<CString, cxuint> KernelMap;
659private:
660    friend class AsmStreamInputFilter;
661    friend class AsmMacroInputFilter;
662    friend class AsmExpression;
663    friend class AsmFormatHandler;
664    friend class AsmRawCodeHandler;
665    friend class AsmAmdHandler;
666    friend class AsmAmdCL2Handler;
667    friend class AsmGalliumHandler;
668    friend class AsmROCmHandler;
669    friend class ISAAssembler;
670   
671    friend struct AsmParseUtils; // INTERNAL LOGIC
672    friend struct AsmPseudoOps; // INTERNAL LOGIC
673    friend struct AsmGalliumPseudoOps; // INTERNAL LOGIC
674    friend struct AsmAmdPseudoOps; // INTERNAL LOGIC
675    friend struct AsmAmdCL2PseudoOps; // INTERNAL LOGIC
676    friend struct GCNAsmUtils; // INTERNAL LOGIC
677
678    Array<CString> filenames;
679    BinaryFormat format;
680    GPUDeviceType deviceType;
681    uint32_t driverVersion;
682    bool _64bit;    ///
683    bool good;
684    bool resolvingRelocs;
685    ISAAssembler* isaAssembler;
686    std::vector<DefSym> defSyms;
687    std::vector<CString> includeDirs;
688    std::vector<AsmSection> sections;
689    AsmSymbolMap symbolMap;
690    std::unordered_set<AsmSymbolEntry*> symbolSnapshots;
691    std::vector<AsmRelocation> relocations;
692    MacroMap macroMap;
693    KernelMap kernelMap;
694    std::vector<AsmKernel> kernels;
695    Flags flags;
696    uint64_t macroCount;
697    uint64_t localCount; // macro's local count
698    bool alternateMacro;
699    bool buggyFPLit;
700   
701    cxuint inclusionLevel;
702    cxuint macroSubstLevel;
703    cxuint repetitionLevel;
704    bool lineAlreadyRead; // if line already read
705   
706    size_t lineSize;
707    const char* line;
708    bool endOfAssembly;
709   
710    cxuint filenameIndex;
711    std::stack<AsmInputFilter*> asmInputFilters;
712    AsmInputFilter* currentInputFilter;
713   
714    std::ostream& messageStream;
715    std::ostream& printStream;
716   
717    AsmFormatHandler* formatHandler;
718   
719    std::stack<AsmClause> clauses;
720   
721    cxuint currentKernel;
722    cxuint& currentSection;
723    uint64_t& currentOutPos;
724   
725    AsmSourcePos getSourcePos(LineCol lineCol) const
726    {
727        return { currentInputFilter->getMacroSubst(), currentInputFilter->getSource(),
728            lineCol.lineNo, lineCol.colNo };
729    }
730   
731    AsmSourcePos getSourcePos(size_t pos) const
732    { return currentInputFilter->getSourcePos(pos); }
733    AsmSourcePos getSourcePos(const char* linePtr) const
734    { return getSourcePos(linePtr-line); }
735   
736    void printWarning(const AsmSourcePos& pos, const char* message);
737    void printError(const AsmSourcePos& pos, const char* message);
738   
739    void printWarning(const char* linePtr, const char* message)
740    { printWarning(getSourcePos(linePtr), message); }
741    void printError(const char* linePtr, const char* message)
742    { printError(getSourcePos(linePtr), message); }
743   
744    void printWarning(LineCol lineCol, const char* message)
745    { printWarning(getSourcePos(lineCol), message); }
746    void printError(LineCol lineCol, const char* message)
747    { printError(getSourcePos(lineCol), message); }
748   
749    LineCol translatePos(const char* linePtr) const
750    { return currentInputFilter->translatePos(linePtr-line); }
751    LineCol translatePos(size_t pos) const
752    { return currentInputFilter->translatePos(pos); }
753   
754    bool parseLiteral(uint64_t& value, const char*& linePtr);
755    bool parseString(std::string& outString, const char*& linePtr);
756   
757    enum class ParseState
758    {
759        FAILED = 0,
760        PARSED,
761        MISSING // missing element
762    };
763   
764    /** parse symbol
765     * \return state
766     */
767    ParseState parseSymbol(const char*& linePtr, AsmSymbolEntry*& entry,
768                   bool localLabel = true, bool dontCreateSymbol = false);
769    bool skipSymbol(const char*& linePtr);
770   
771    bool setSymbol(AsmSymbolEntry& symEntry, uint64_t value, cxuint sectionId);
772   
773    bool assignSymbol(const CString& symbolName, const char* symbolPlace,
774                  const char* linePtr, bool reassign = true, bool baseExpr = false);
775   
776    bool assignOutputCounter(const char* symbolPlace, uint64_t value, cxuint sectionId,
777                     cxbyte fillValue = 0);
778   
779    void parsePseudoOps(const CString& firstName, const char* stmtPlace,
780                const char* linePtr);
781   
782    /// exitm - exit macro mode
783    bool skipClauses(bool exitm = false);
784    bool putMacroContent(RefPtr<AsmMacro> macro);
785    bool putRepetitionContent(AsmRepeat& repeat);
786   
787    void initializeOutputFormat();
788   
789    bool pushClause(const char* string, AsmClauseType clauseType)
790    {
791        bool included; // to ignore
792        return pushClause(string, clauseType, true, included);
793    }
794    bool pushClause(const char* string, AsmClauseType clauseType,
795                  bool satisfied, bool& included);
796     // return false when failed (for example no clauses)
797    bool popClause(const char* string, AsmClauseType clauseType);
798   
799    /// returns false when includeLevel is too deep, throw error if failed a file opening
800    bool includeFile(const char* pseudoOpPlace, const std::string& filename);
801   
802    ParseState makeMacroSubstitution(const char* string);
803   
804    bool parseMacroArgValue(const char*& linePtr, std::string& outStr);
805   
806    void putData(size_t size, const cxbyte* data)
807    {
808        AsmSection& section = sections[currentSection];
809        section.content.insert(section.content.end(), data, data+size);
810        currentOutPos += size;
811    }
812
813    cxbyte* reserveData(size_t size, cxbyte fillValue = 0);
814   
815    void goToMain(const char* pseudoOpPlace);
816    void goToKernel(const char* pseudoOpPlace, const char* kernelName);
817    void goToSection(const char* pseudoOpPlace, const char* sectionName, uint64_t align=0);
818    void goToSection(const char* pseudoOpPlace, const char* sectionName,
819                     AsmSectionType type, Flags flags, uint64_t align=0);
820    void goToSection(const char* pseudoOpPlace, cxuint sectionId, uint64_t align=0);
821   
822    void printWarningForRange(cxuint bits, uint64_t value, const AsmSourcePos& pos,
823                  cxbyte signess = WS_BOTH);
824   
825    bool checkReservedName(const CString& name);
826   
827    bool isAddressableSection() const
828    {
829        return currentSection==ASMSECT_ABS ||
830                    (sections[currentSection].flags & ASMSECT_ADDRESSABLE) != 0;
831    }
832    bool isWriteableSection() const
833    {
834        return currentSection!=ASMSECT_ABS &&
835                (sections[currentSection].flags & ASMSECT_WRITEABLE) != 0;
836    }
837    bool isResolvableSection() const
838    {
839        return currentSection==ASMSECT_ABS ||
840                (sections[currentSection].flags & ASMSECT_UNRESOLVABLE) == 0;
841    }
842    bool isResolvableSection(cxuint sectionId) const
843    {
844        return sectionId==ASMSECT_ABS ||
845                (sections[sectionId].flags & ASMSECT_UNRESOLVABLE) == 0;
846    }
847   
848protected:   
849    /// helper for testing
850    bool readLine();
851public:
852    /// constructor with filename and input stream
853    /**
854     * \param filename filename
855     * \param input input stream
856     * \param flags assembler flags
857     * \param format output format type
858     * \param deviceType GPU device type
859     * \param msgStream stream for warnings and errors
860     * \param printStream stream for printing message by .print pseudo-ops
861     */
862    explicit Assembler(const CString& filename, std::istream& input, Flags flags = 0,
863              BinaryFormat format = BinaryFormat::AMD,
864              GPUDeviceType deviceType = GPUDeviceType::CAPE_VERDE,
865              std::ostream& msgStream = std::cerr, std::ostream& printStream = std::cout);
866   
867    /// constructor with filename and input stream
868    /**
869     * \param filenames filenames
870     * \param flags assembler flags
871     * \param format output format type
872     * \param deviceType GPU device type
873     * \param msgStream stream for warnings and errors
874     * \param printStream stream for printing message by .print pseudo-ops
875     */
876    explicit Assembler(const Array<CString>& filenames, Flags flags = 0,
877              BinaryFormat format = BinaryFormat::AMD,
878              GPUDeviceType deviceType = GPUDeviceType::CAPE_VERDE,
879              std::ostream& msgStream = std::cerr, std::ostream& printStream = std::cout);
880    /// destructor
881    ~Assembler();
882   
883    /// main routine to assemble code
884    bool assemble();
885   
886    /// write binary to file
887    void writeBinary(const char* filename) const;
888    /// write binary to stream
889    void writeBinary(std::ostream& outStream) const;
890    /// write binary to array
891    void writeBinary(Array<cxbyte>& array) const;
892   
893    /// get AMD driver version
894    uint32_t getDriverVersion() const
895    { return driverVersion; }
896    /// set AMD driver version
897    void setDriverVersion(uint32_t driverVersion)
898    { this->driverVersion = driverVersion; }
899   
900    /// get GPU device type
901    GPUDeviceType getDeviceType() const
902    { return deviceType; }
903    /// set GPU device type
904    void setDeviceType(const GPUDeviceType deviceType)
905    { this->deviceType = deviceType; }
906    /// get binary format
907    BinaryFormat getBinaryFormat() const
908    { return format; }
909    /// set binary format
910    void setBinaryFormat(BinaryFormat binFormat)
911    { format = binFormat; }
912    /// get bitness
913    bool is64Bit() const
914    { return _64bit; }
915    /// set bitness
916    void set64Bit(bool this64Bit)
917    {  _64bit = this64Bit; }
918    /// get flags
919    Flags getFlags() const
920    { return flags; }
921    /// set flags
922    void setFlags(Flags flags)
923    { this->flags = flags; }
924    /// get include directory list
925    const std::vector<CString>& getIncludeDirs() const
926    { return includeDirs; }
927    /// adds include directory
928    void addIncludeDir(const CString& includeDir);
929    /// get symbols map
930    const AsmSymbolMap& getSymbolMap() const
931    { return symbolMap; }
932    /// get sections
933    const std::vector<AsmSection>& getSections() const
934    { return sections; }
935    /// get kernel map
936    const KernelMap& getKernelMap() const
937    { return kernelMap; }
938    /// get kernels
939    const std::vector<AsmKernel>& getKernels() const
940    { return kernels; }
941   
942    /// returns true if symbol contains absolute value
943    bool isAbsoluteSymbol(const AsmSymbol& symbol) const;
944   
945    /// add initiali defsyms
946    void addInitialDefSym(const CString& symName, uint64_t value);
947   
948    /// get format handler
949    const AsmFormatHandler* getFormatHandler() const
950    { return formatHandler; }
951};
952
953inline void ISAAssembler::printWarning(const char* linePtr, const char* message)
954{ return assembler.printWarning(linePtr, message); }
955
956inline void ISAAssembler::printError(const char* linePtr, const char* message)
957{ return assembler.printError(linePtr, message); }
958
959inline void ISAAssembler::printWarningForRange(cxuint bits, uint64_t value,
960                   const AsmSourcePos& pos, cxbyte signess)
961{ return assembler.printWarningForRange(bits, value, pos, signess); }
962
963inline void ISAAssembler::printWarning(const AsmSourcePos& sourcePos, const char* message)
964{ return assembler.printWarning(sourcePos, message); }
965
966inline void ISAAssembler::printError(const AsmSourcePos& sourcePos, const char* message)
967{ return assembler.printError(sourcePos, message); }
968
969};
970
971#endif
Note: See TracBrowser for help on using the repository browser.