gen32bit.pas

Переключить прокрутку окна
Загрузить этот исходный код

{
    Этот исходный текст является частью Продвинутого векторного транслятора.

    Copyright © 2017 Малик Разработчик

    Это свободная программа: вы можете перераспространять её и/или
    изменять её на условиях Стандартной общественной лицензии GNU в том виде,
    в каком она была опубликована Фондом свободного программного обеспечения;
    либо версии 3 лицензии, либо (по вашему выбору) любой более поздней версии.

    Эта программа распространяется в надежде, что она может быть полезна,
    но БЕЗО ВСЯКИХ ГАРАНТИЙ; даже без неявной гарантии ТОВАРНОГО ВИДА
    или ПРИГОДНОСТИ ДЛЯ ОПРЕДЕЛЁННЫХ ЦЕЛЕЙ. Подробнее см. в Стандартной
    общественной лицензии GNU.

    Вы должны были получить копию Стандартной общественной лицензии GNU
    вместе с этой программой. Если это не так, см.
    <http://www.gnu.org/licenses/>.
}

unit Gen32bit;

{$MODE DELPHI,EXTENDEDSYNTAX ON}

interface

uses
    Lang, Utils, IOStream, TranIntf, TranType, TranTree, BuildLex, BuildFTr, GenX86, Gen16bit;

{$ASMMODE INTEL,CALLING REGISTER,INLINE ON,GOTO ON}
{$H+,I-,J-,M-,Q-,R-,T-}

type
    RegisterStack32bit = class;
    TranslatorBuilderOf32bitCode = class;

    RegisterStack32bit = class(RegisterStack16bit)
    public
        constructor create(const usingGPRS, usingXMMS: short_Array1d;
                usingGPRAsPointerAndArray, usingGPRAsPointerAndIndex: int);
        procedure storeRegs(count: int; g: TextGenerator); override;
        procedure restoreRegs(g: TextGenerator); override;
        function getNextUsedGPR(regGPR: int): int; override;
        function changeToGPR16bit(index: int): int; override;
        function changeToGPR32bit(index: int): int; override;
        function allocateGPR16bit(g: TextGenerator): int; override;
        function allocateGPR32bit(g: TextGenerator): int; override;
        function allocateGPRForArray(g: TextGenerator): int; override;
        function allocateGPRForIndex(g: TextGenerator): int; override;
        function allocateGPRForPointer(g: TextGenerator): int; override;
    protected
        procedure checkRegister(reg: int); override;
    end;

    TranslatorBuilderOf32bitCode = class(TranslatorBuilderOf16bitCode)
    public
        const LABEL_POOL_FUNCS_LENGTH = 'L.P.FUNCS.LEN';
        const LABEL_POOL_FUNCS_CONTENT = 'L.P.FUNCS.CON';
        const FUNCTION_FLOAT_TO_INT = TranslatorTreeBuilder.NAMESPACE_SYSTEM + '.floatToInt';
        const FUNCTION_DOUBLE_TO_INT = TranslatorTreeBuilder.NAMESPACE_SYSTEM + '.doubleToInt';
        const FUNCTION_REAL_TO_INT = TranslatorTreeBuilder.NAMESPACE_SYSTEM + '.realToInt';

    public
        constructor create(); overload;
        constructor create(generator: TextGenerator; owning: boolean); overload;
        destructor destroy; override;
        procedure buildTargetCode(programme: BuilderOfTrees; stream: Output); override;
    strict private
        poolOfFunctions: Vector;
        procedure translateEntryEquality(entry: NamespaceEntry);
        procedure translateEntryVariable(entry: NamespaceEntry);
        procedure translateEntryFunction(entry: NamespaceEntry; programme: BuilderOfTrees);
        procedure translateStructure(structure: TypeStructure);
        procedure translateConstant(constant: GlobalConstant);
        procedure translateVariable(variable: GlobalVariable);
        procedure translateFunction(func: GlobalFunction; programme: BuilderOfTrees);
        procedure translateTree(tree: SyntaxTree);
        procedure translateNode(node: SyntaxNode; stack: RegisterStack);
        procedure translateSwitch(node: SyntaxNode; stack: RegisterStack);
        procedure writePools();
        function insertArguments(args: TypeFunction; offset: int): int;
        function insertLocalVars(tree: SyntaxTree; offset: int): int;
        function getMemoryLocation(node: SyntaxNode; stack: RegisterStack;
                hasValueForWrite: boolean): MemoryLocation;
    protected
        property programmeFunctions: Vector read poolOfFunctions;
    end;

implementation

{ RegisterStack32bit }

constructor RegisterStack32bit.create(const usingGPRS, usingXMMS: short_Array1d;
        usingGPRAsPointerAndArray, usingGPRAsPointerAndIndex: int);
begin
    inherited create(usingGPRS, usingXMMS, usingGPRAsPointerAndArray, usingGPRAsPointerAndIndex);
end;

procedure RegisterStack32bit.storeRegs(count: int; g: TextGenerator);
var
    nonPushable: boolean;
    i: int;
    j: int;
    ofs: int;
    reg1: int;
    sbase: int;
    ssize: int;
    stack: short_Array1d;
    sr1: String;
    sESP: String;
begin
    { Инструкции, вставляемые этим методом, не модифицируют регистр флагов. }
    sbase := self.sbase;
    ssize := self.ssize;
    stack := self.stack;
    nonPushable :=  false;
    i := sbase;
    j := 0;
    ofs := 0;
    while (i < ssize) and (j < count) do begin
        reg1 := stack[i];
        case reg1 of
        EAX, ECX, EDX, EBX, ESP, EBP, ESI, EDI: begin
            inc(ofs, 4);
        end;
        (XMM0 + XSINT)..(XMM7 + XSINT), (XMM0 + XSFLOAT)..(XMM7 + XSFLOAT): begin
            nonPushable := true;
            inc(ofs, 4);
        end;
        (XMM0 + XSLONG)..(XMM7 + XSLONG), (XMM0 + XSDOUBLE)..(XMM7 + XSDOUBLE), MM0..MM7: begin
            nonPushable := true;
            inc(ofs, 8);
        end;
        ST0..ST7: begin
            nonPushable := true;
            inc(ofs, 12);
        end;
        (XMM0 + XPFLOAT)..(XMM7 + XPFLOAT), (XMM0 + XPDOUBLE)..(XMM7 + XPDOUBLE),
        (XMM0 + XPINT)..(XMM7 + XPINT), (XMM0 + XPLONG)..(XMM7 + XPLONG): begin
            nonPushable := true;
            inc(ofs, 16);
        end;
        end;
        inc(i);
        inc(j);
    end;
    sESP := g.registerToString(ESP);
    if nonPushable then begin
        g.writeInstruction('lea', sESP, g.memoryToString(MNONE, ESP, -ofs));
    end;
    i := sbase;
    j := 0;
    while (i < ssize) and (j < count) do begin
        reg1 := stack[i];
        sr1 := g.registerToString(reg1);
        case reg1 of
        EAX, ECX, EDX, EBX, ESP, EBP, ESI, EDI: begin
            if nonPushable then begin
                dec(ofs, 4);
                g.writeInstruction('mov', g.memoryToString(MNONE, ESP, ofs), sr1);
            end else begin
                g.writeInstruction('push', sr1);
            end;
        end;
        (XMM0 + XSINT)..(XMM7 + XSINT): begin
            dec(ofs, 4);
            g.writeInstruction('movd', g.memoryToString(MNONE, ESP, ofs), sr1);
        end;
        (XMM0 + XSFLOAT)..(XMM7 + XSFLOAT): begin
            dec(ofs, 4);
            g.writeInstruction('movss', g.memoryToString(MNONE, ESP, ofs), sr1);
        end;
        (XMM0 + XSLONG)..(XMM7 + XSLONG), MM0..MM7: begin
            dec(ofs, 8);
            g.writeInstruction('movq', g.memoryToString(MNONE, ESP, ofs), sr1);
        end;
        (XMM0 + XSDOUBLE)..(XMM7 + XSDOUBLE): begin
            dec(ofs, 8);
            g.writeInstruction('movsd', g.memoryToString(MNONE, ESP, ofs), sr1);
        end;
        ST: begin
            dec(ofs, 12);
            g.writeInstruction('fstp', g.memoryToString(MREAL, ESP, ofs));
            { g.writeInstruction('fdecstp'); }
        end;
        ST1..ST7: begin
            dec(ofs, 12);
            g.writeInstruction('fxch', sr1);
            g.writeInstruction('fstp', g.memoryToString(MREAL, ESP, ofs));
            if reg1 > ST1 then begin
                g.writeInstruction('fld', g.registerToString(reg1 - 1));
                g.writeInstruction('ffree', sr1);
            end;
        end;
        (XMM0 + XPINT)..(XMM7 + XPINT), (XMM0 + XPLONG)..(XMM7 + XPLONG): begin
            dec(ofs, 16);
            g.writeInstruction('movdqu', g.memoryToString(MNONE, ESP, ofs), sr1);
        end;
        (XMM0 + XPFLOAT)..(XMM7 + XPFLOAT): begin
            dec(ofs, 16);
            g.writeInstruction('movups', g.memoryToString(MNONE, ESP, ofs), sr1);
        end;
        (XMM0 + XPDOUBLE)..(XMM7 + XPDOUBLE): begin
            dec(ofs, 16);
            g.writeInstruction('movupd', g.memoryToString(MNONE, ESP, ofs), sr1);
        end;
        end;
        inc(i);
        inc(j);
    end;
    self.sbase := i;
end;

procedure RegisterStack32bit.restoreRegs(g: TextGenerator);
var
    nonPopable: boolean;
    i: int;
    nbs: int;
    ofs: int;
    reg1: int;
    reglf: int;
    sbase: int;
    limit: int;
    stack: short_Array1d;
    sr1: String;
    sESP: String;
begin
    { Инструкции, вставляемые этим методом, не модифицируют регистр флагов. }
    sbase := self.sbase;
    limit := self.ssize - 1;
    stack := self.stack;
    reglf := ST - 1;
    for i := sbase to limit do begin
        reg1 := stack[i];
        if (reg1 >= ST0) and (reg1 <= ST7) then begin
            reglf := reg1;
            break;
        end;
    end;
    nonPopable := false;
    i := sbase;
    while i > 0 do begin
        reg1 := stack[i - 1];
        if (reg1 >= ST0) and (reg1 <= ST7) and (reglf < ST7) then begin
            inc(reglf);
            reg1 := reglf;
            stack[i - 1] := short(reg1);
        end;
        if isUsedRegister(reg1) then begin
            break;
        end;
        dec(i);
        self.sbase := i;
        case reg1 of
        MM0..MM7, ST0..ST7,
        (XMM0 + XPINT)..(XMM7 + XPINT), (XMM0 + XPLONG)..(XMM7 + XPLONG),
        (XMM0 + XSINT)..(XMM7 + XSINT), (XMM0 + XSLONG)..(XMM7 + XSLONG),
        (XMM0 + XPFLOAT)..(XMM7 + XPFLOAT), (XMM0 + XPDOUBLE)..(XMM7 + XPDOUBLE),
        (XMM0 + XSFLOAT)..(XMM7 + XSFLOAT), (XMM0 + XSDOUBLE)..(XMM7 + XSDOUBLE):
            nonPopable := true;
        EAX, ECX, EDX, EBX, ESP, EBP, ESI, EDI: ;
        end;
    end;
    nbs := i;
    ofs := 0;
    sESP := g.registerToString(ESP);
    for i := sbase - 1 downto nbs do begin
        reg1 := stack[i];
        sr1 := g.registerToString(reg1);
        case reg1 of
        EAX, ECX, EDX, EBX, ESP, EBP, ESI, EDI: begin
            if nonPopable then begin
                g.writeInstruction('mov', sr1, g.memoryToString(MNONE, ESP, ofs));
                inc(ofs, 4);
            end else begin
                g.writeInstruction('pop', sr1);
            end;
        end;
        (XMM0 + XSINT)..(XMM7 + XSINT): begin
            g.writeInstruction('movd', sr1, g.memoryToString(MNONE, ESP, ofs));
            inc(ofs, 4);
        end;
        (XMM0 + XSFLOAT)..(XMM7 + XSFLOAT): begin
            g.writeInstruction('movss', sr1, g.memoryToString(MNONE, ESP, ofs));
            inc(ofs, 4);
        end;
        (XMM0 + XSLONG)..(XMM7 + XSLONG), MM0..MM7: begin
            g.writeInstruction('movq', sr1, g.memoryToString(MNONE, ESP, ofs));
            inc(ofs, 8);
        end;
        (XMM0 + XSDOUBLE)..(XMM7 + XSDOUBLE): begin
            g.writeInstruction('movsd', sr1, g.memoryToString(MNONE, ESP, ofs));
            inc(ofs, 8);
        end;
        ST0..ST6: begin
            g.writeInstruction('fld', g.memoryToString(MREAL, ESP, ofs));
            if reg1 > ST0 then begin
                g.writeInstruction('fstp', g.registerToString(reg1 + 1));
            end;
            inc(ofs, 12);
        end;
        ST7: begin
            g.writeInstruction('fld', g.memoryToString(MREAL, ESP, ofs));
            g.writeInstruction('fincstp');
            inc(ofs, 12);
        end;
        (XMM0 + XPINT)..(XMM7 + XPINT), (XMM0 + XPLONG)..(XMM7 + XPLONG): begin
            g.writeInstruction('movdqu', sr1, g.memoryToString(MNONE, ESP, ofs));
            inc(ofs, 16);
        end;
        (XMM0 + XPFLOAT)..(XMM7 + XPFLOAT): begin
            g.writeInstruction('movups', sr1, g.memoryToString(MNONE, ESP, ofs));
            inc(ofs, 16);
        end;
        (XMM0 + XPDOUBLE)..(XMM7 + XPDOUBLE): begin
            g.writeInstruction('movupd', sr1, g.memoryToString(MNONE, ESP, ofs));
            inc(ofs, 16);
        end;
        end;
    end;
    if nonPopable then begin
        g.writeInstruction('lea', sESP, g.memoryToString(MNONE, ESP, ofs));
    end;
end;

function RegisterStack32bit.getNextUsedGPR(regGPR: int): int;
var
    i: int;
    regcm: int;
    regus: int;
    using: short_Array1d;
begin
    using := self.usingGPRs;
    regcm := EAX + (regGPR and $0f);
    result := EAX + (using[0] and $0f);
    for i := length(using) - 1 downto 0 do begin
        regus := EAX + (using[i] and $0f);
        if regus = regcm then begin
            exit;
        end;
        result := regus;
    end;
end;

function RegisterStack32bit.changeToGPR16bit(index: int): int;
begin
    result := -1;
end;

function RegisterStack32bit.changeToGPR32bit(index: int): int;
var
    ssize: int;
    stack: short_Array1d;
begin
    ssize := self.ssize;
    if (index < 0) or (index >= ssize) then begin
        raise IndexOutOfBoundsException.create(msgIndexOutOfBounds);
    end;
    stack := self.stack;
    index := ssize - index - 1;
    result := stack[index];
    if not isRegisterGP(result) then begin
        result := -1;
        exit;
    end;
    result := EAX + (result and $0f);
    stack[index] := short(result);
end;

function RegisterStack32bit.allocateGPR16bit(g: TextGenerator): int;
begin
    result := -1;
end;

function RegisterStack32bit.allocateGPR32bit(g: TextGenerator): int;
var
    i: int;
    regst: int;
    uslim: int;
    sbase: int;
    limit: int;
    stack: short_Array1d;
    using: short_Array1d;
begin
    result := -1;
    using := self.usingGPRs;
    stack := self.stack;
    limit := self.ssize - 1;
    sbase := self.sbase;
    uslim := length(using) - 1;
    for i := limit downto 0 do begin
        regst := getCommonRegister(stack[i]);
        if result < 0 then begin
            if isUsing(regst, using) then begin
                result := getCommonRegister(getNextUsedGPR(regst));
            end;
        end else begin
            if regst = result then begin
                regst := EAX + (regst and $0f);
                if i >= sbase then begin
                    storeRegs(i - sbase + 1, g);
                end;
                pushReg(regst);
                result := regst;
                exit;
            end;
        end;
    end;
    if result >= 0 then begin
        regst := EAX + (result and $0f);
        pushReg(regst);
        result := regst;
        exit;
    end;
    for i := 0 to uslim do begin
        regst := EAX + (using[i] and $0f);
        if not isUsedRegister(regst) then begin
            pushReg(regst);
            result := regst;
            exit;
        end;
    end;
    for i := sbase to limit do begin
        regst := getCommonRegister(stack[i]);
        if isUsing(regst, using) then begin
            regst := EAX + (regst and $0f);
            storeRegs(i - sbase + 1, g);
            pushReg(regst);
            result := regst;
            exit;
        end;
    end;
    result := -1;
end;

function RegisterStack32bit.allocateGPRForArray(g: TextGenerator): int;
var
    i: int;
    regst: int;
    regAr: int;
    sbase: int;
    limit: int;
    stack: short_Array1d;
begin
    result := -1;
    stack := self.stack;
    limit := self.ssize - 1;
    sbase := self.sbase;
    regAr := getCommonRegister(self.usingGPRAsPointerAndArray);
    for i := limit downto 0 do begin
        regst := getCommonRegister(stack[i]);
        if regst = regAr then begin
            regst := EAX + (regst and $0f);
            if i >= sbase then begin
                storeRegs(i - sbase + 1, g);
            end;
            pushReg(regst);
            result := regst;
            exit;
        end;
    end;
    regst := EAX + (regAr and $0f);
    if not isUsedRegister(regst) then begin
        pushReg(regst);
        result := regst;
        exit;
    end;
    for i := sbase to limit do begin
        regst := getCommonRegister(stack[i]);
        if regst = regAr then begin
            regst := EAX + (regst and $0f);
            storeRegs(i - sbase + 1, g);
            pushReg(regst);
            result := regst;
            exit;
        end;
    end;
end;

function RegisterStack32bit.allocateGPRForIndex(g: TextGenerator): int;
var
    i: int;
    regst: int;
    regId: int;
    sbase: int;
    limit: int;
    stack: short_Array1d;
begin
    result := -1;
    stack := self.stack;
    limit := self.ssize - 1;
    sbase := self.sbase;
    regId := getCommonRegister(self.usingGPRAsPointerAndIndex);
    for i := limit downto 0 do begin
        regst := getCommonRegister(stack[i]);
        if regst = regId then begin
            regst := EAX + (regst and $0f);
            if i >= sbase then begin
                storeRegs(i - sbase + 1, g);
            end;
            pushReg(regst);
            result := regst;
            exit;
        end;
    end;
    regst := EAX + (regId and $0f);
    if not isUsedRegister(regst) then begin
        pushReg(regst);
        result := regst;
        exit;
    end;
    for i := sbase to limit do begin
        regst := getCommonRegister(stack[i]);
        if regst = regId then begin
            regst := EAX + (regst and $0f);
            storeRegs(i - sbase + 1, g);
            pushReg(regst);
            result := regst;
            exit;
        end;
    end;
end;

function RegisterStack32bit.allocateGPRForPointer(g: TextGenerator): int;
var
    i: int;
    regst: int;
    regP1: int;
    regP2: int;
    sbase: int;
    limit: int;
    stack: short_Array1d;
begin
    result := -1;
    stack := self.stack;
    limit := self.ssize - 1;
    sbase := self.sbase;
    regP1 := getCommonRegister(self.usingGPRAsPointerAndArray);
    regP2 := getCommonRegister(self.usingGPRAsPointerAndIndex);
    for i := limit downto 0 do begin
        regst := getCommonRegister(stack[i]);
        if result < 0 then begin
            if regst = regP1 then begin
                result := regP2;
            end else
            if regst = regP2 then begin
                result := regP1;
            end;
        end else begin
            if regst = result then begin
                regst := EAX + (regst and $0f);
                if i >= sbase then begin
                    storeRegs(i - sbase + 1, g);
                end;
                pushReg(regst);
                result := regst;
                exit;
            end;
        end;
    end;
    if result >= 0 then begin
        regst := EAX + (result and $0f);
        pushReg(regst);
        result := regst;
        exit;
    end;
    regst := EAX + (regP1 and $0f);
    if not isUsedRegister(regst) then begin
        pushReg(regst);
        result := regst;
        exit;
    end;
    regst := EAX + (regP2 and $0f);
    if not isUsedRegister(regst) then begin
        pushReg(regst);
        result := regst;
        exit;
    end;
    for i := sbase to limit do begin
        regst := getCommonRegister(stack[i]);
        if (regst = regP1) or (regst = regP2) then begin
            regst := EAX + (regst and $0f);
            storeRegs(i - sbase + 1, g);
            pushReg(regst);
            result := regst;
            exit;
        end;
    end;
    result := -1;
end;

procedure RegisterStack32bit.checkRegister(reg: int);
begin
    case reg of
    EAX, ECX, EDX, EBX, ESP, EBP, ESI, EDI, MM0..MM7, ST0..ST7,
    (XMM0 + XPINT)..(XMM7 + XPINT), (XMM0 + XPLONG)..(XMM7 + XPLONG),
    (XMM0 + XSINT)..(XMM7 + XSINT), (XMM0 + XSLONG)..(XMM7 + XSLONG),
    (XMM0 + XPFLOAT)..(XMM7 + XPFLOAT), (XMM0 + XPDOUBLE)..(XMM7 + XPDOUBLE),
    (XMM0 + XSFLOAT)..(XMM7 + XSFLOAT), (XMM0 + XSDOUBLE)..(XMM7 + XSDOUBLE): ;
    else
        raise IllegalArgumentException.create(msgIllegalRegisters);
    end;
end;

{ TranslatorBuilderOf32bitCode }

constructor TranslatorBuilderOf32bitCode.create();
begin
    inherited create(TextGenerator.create(), true);
    self.poolOfFunctions := Vector.create();
end;

constructor TranslatorBuilderOf32bitCode.create(generator: TextGenerator; owning: boolean);
begin
    inherited create(generator, owning);
    self.poolOfFunctions := Vector.create();
end;

destructor TranslatorBuilderOf32bitCode.destroy;
begin
    poolOfFunctions.free();
    inherited destroy;
end;

procedure TranslatorBuilderOf32bitCode.buildTargetCode(programme: BuilderOfTrees; stream: Output);
var
    i: int;
    j: int;
    org: int;
    elimit: int;
    mlimit: int;
    module: Namespace;
    entry: NamespaceEntry;
    pentry: GlobalFunction;
    g: TextGenerator;
begin
    g := self.generator;
    g.clear();
    try
        programmeReals.clear();
        programmeFloats.clear();
        programmeDoubles.clear();
        programmeStrings.clear();
        programmeFunctions.clear();
        entry := programme.systemNamespace.findEntry(CONSTANT_ORG, false);
        if entry is GlobalConstant then begin
            org := (entry as GlobalConstant).intValue;
        end else begin
            org := 0;
        end;
        entry := nil;
        pentry := programme.entryPoint;
        g.writeDirectives(MODE_32_BIT, org, encode(pentry.name));
        g.writeEmptyLine();
        g.writeEmptyLine();
        g.writeCommentToLineEnd('constant of boolean type');
        g.writeEquality('false', g.immediateToString(0));
        g.writeEquality('true', g.immediateToString(1));
        g.writeEmptyLine();
        g.writeEmptyLine();
        g.writeCommentToLineEnd('constant null');
        g.writeEquality('null', g.immediateToString(0));
        g.writeEmptyLine();
        mlimit := programme.getNamespacesCount() - 1;
        for j := 0 to mlimit do begin
            module := programme.getNamespace(j);
            if length(module.name) <= 0 then begin
                continue;
            end;
            elimit := module.getEntriesCount() - 1;
            for i := 0 to elimit do begin
                translateEntryEquality(module.getEntry(i));
            end;
        end;
        g.beginCodeSection();
        translateFunction(pentry, programme);
        for j := 0 to mlimit do begin
            module := programme.getNamespace(j);
            if length(module.name) <= 0 then begin
                continue;
            end;
            elimit := module.getEntriesCount() - 1;
            for i := 0 to elimit do begin
                translateEntryFunction(module.getEntry(i), programme);
            end;
        end;
        g.beginDataSection();
        for j := 0 to mlimit do begin
            module := programme.getNamespace(j);
            if length(module.name) <= 0 then begin
                continue;
            end;
            elimit := module.getEntriesCount() - 1;
            for i := 0 to elimit do begin
                translateEntryVariable(module.getEntry(i));
            end;
        end;
        g.beginPoolSection();
        writePools();
        g.writeProgrammeTail();
        g.writeEmptyLine();
        g.writeCommentToLineEnd('programme end');
        g.writeAlignGlobal(4);
        g.writeLabelLong(LABEL_PROG_END);
        g.optimize();
    finally
        stream.write(stringToByteArray(g.toString()));
    end;
end;

procedure TranslatorBuilderOf32bitCode.translateEntryEquality(entry: NamespaceEntry);
begin
    if entry is TypeStructure then begin
        translateStructure(entry as TypeStructure);
    end else
    if entry is GlobalConstant then begin
        translateConstant(entry as GlobalConstant);
    end;
end;

procedure TranslatorBuilderOf32bitCode.translateEntryVariable(entry: NamespaceEntry);
begin
    if not (entry is GlobalConstant) and (entry is GlobalVariable) then begin
        translateVariable(entry as GlobalVariable);
    end;
end;

procedure TranslatorBuilderOf32bitCode.translateEntryFunction(entry: NamespaceEntry;
        programme: BuilderOfTrees);
begin
    if entry is GlobalFunction then begin
        translateFunction(entry as GlobalFunction, programme);
    end;
end;

procedure TranslatorBuilderOf32bitCode.translateStructure(structure: TypeStructure);
var
    i: int;
    limit: int;
    field: StructureField;
    g: TextGenerator;
    ename: String;
    fname: String;
begin
    g := self.generator;
    ename := getEntryFullName(structure as NamespaceEntry);
    g.writeEmptyLine();
    g.writeCommentToLineEnd('structure ' + ename);
    repeat
        limit := structure.getFieldsCount() - 1;
        for i := 0 to limit do begin
            field := structure.getField(i);
            fname := encode(field.name);
            if length(fname) > 0 then begin
                g.writeEquality(ename + '.' + fname, g.immediateToString(field.offset));
            end;
        end;
        structure := structure.ancestor;
    until structure = nil;
    g.writeEmptyLine();
end;

procedure TranslatorBuilderOf32bitCode.translateConstant(constant: GlobalConstant);
var
    g: TextGenerator;
    ename: String;
begin
    g := self.generator;
    ename := getEntryFullName(constant);
    g.writeEmptyLine();
    g.writeCommentToLineEnd('constant ' + ename);
    case constant.dataType.kind of
    TranslatorType.KIND_BOOLEAN:
        if constant.booleanValue = true then begin
            g.writeEquality(ename, 'true');
        end else begin
            g.writeEquality(ename, 'false');
        end;
    TranslatorType.KIND_CHAR:
        g.writeEquality(ename, g.immediateToString(constant.charValue));
    TranslatorType.KIND_BYTE:
        g.writeEquality(ename, g.immediateToString(constant.byteValue));
    TranslatorType.KIND_SHORT:
        g.writeEquality(ename, g.immediateToString(constant.shortValue));
    TranslatorType.KIND_INT:
        g.writeEquality(ename, g.immediateToString(constant.intValue));
    TranslatorType.KIND_FLOAT:
        g.writeEquality(ename, g.memoryToString(MFLOAT, LABEL_POOL_FLOAT_CONTENT,
                programmeFloats.indexAcquire(realToFloat(constant.realValue)) * 4));
    TranslatorType.KIND_DOUBLE:
        g.writeEquality(ename, g.memoryToString(MDOUBLE, LABEL_POOL_DOUBLE_CONTENT,
                programmeDoubles.indexAcquire(realToDouble(constant.realValue)) * 8));
    TranslatorType.KIND_REAL:
        g.writeEquality(ename, g.memoryToStringDecOffset(MREAL, LABEL_POOL_REAL_CONTENT,
                programmeReals.indexAcquire(constant.realValue) * 10));
    end;
    g.writeEmptyLine();
end;

procedure TranslatorBuilderOf32bitCode.translateVariable(variable: GlobalVariable);
var
    vtype: TypeDescriptor;
    g: TextGenerator;
    ename: String;
    szero: String;
begin
    g := self.generator;
    ename := getEntryFullName(variable);
    vtype := variable.dataType;
    g.writeAlignGlobal(4);
    g.writeLabelGlobal(ename);
    g.writeCommentToLineEnd(vtype.toString());
    case vtype.kind of
    TranslatorType.KIND_STRUCT, TranslatorType.KIND_ARRAY, TranslatorType.KIND_FUNC,
    TranslatorType.KIND_BOOLEAN, TranslatorType.KIND_CHAR, TranslatorType.KIND_BYTE,
    TranslatorType.KIND_SHORT, TranslatorType.KIND_INT, TranslatorType.KIND_FLOAT:
        g.writeInstruction('dd', g.immediateToStringInt(0));
    TranslatorType.KIND_DOUBLE:
        g.writeInstruction('dq', g.immediateToStringLong(0));
    TranslatorType.KIND_REAL: begin
        szero := g.immediateToStringShort(0);
        g.writeInstruction('dw', String_Array1d_create([
            szero, szero, szero, szero, szero
        ]));
    end;
    end;
    g.writeEmptyLine();
end;

procedure TranslatorBuilderOf32bitCode.translateFunction(func: GlobalFunction;
        programme: BuilderOfTrees);
var
    interruptWithError: boolean;
    functionWithSFrame: boolean;
    functionIsEntry: boolean;
    i: int;
    limit: int;
    pcount: int;
    pstart: int;
    pfinish: int;
    argumsSize: int;
    localsSize: int;
    lexemes: Lexer;
    tree: SyntaxTree;
    root: SyntaxNode;
    module: Namespace;
    entry: NamespaceEntry;
    ftype: TypeFunction;
    g: TextGenerator;
    comment: String;
    ename: String;
begin
    if func.publicObject then begin
        programmeFunctions.addElement(func);
    end;
    g := self.generator;
    ename := getEntryFullName(func);
    ftype := func.functionType;
    module := func.owner;
    functionIsEntry := length(module.name) <= 0;
    if functionIsEntry = false then begin
        g.writeAlignGlobal(4);
    end;
    g.writeLabelGlobal(ename);
    limit := ftype.getArgumentsCount() - 1;
    comment := ftype.getReturnType().toString();
    if limit >= 0 then begin
        g.writeCommentToLineEnd(comment + '(');
        for i := 0 to limit do with ftype.getArgument(i) do begin
            comment := dataType.toString() + #$20 + encode(name);
            if i < limit then begin
                g.writeCommentWithIdent(comment + ',');
            end else begin
                g.writeCommentWithIdent(comment + ')');
            end;
        end;
    end else begin
        g.writeCommentToLineEnd(comment + '()');
    end;
    lexemes := module.lexemes;
    pcount := 1;
    pstart := func.startPosition + 1;
    pfinish := pstart - 1;
    repeat
        inc(pfinish);
        case lexemes.getType(pfinish) of
        TranslatorLexer.OPENED_CURLY_BRACKET:
            inc(pcount);
        TranslatorLexer.CLOSED_CURLY_BRACKET:
            dec(pcount);
        end;
    until pcount = 0;
    if func.isInterrupt() then begin
        { чтобы функция-прерывание имела параметр «код ошибки», нужно чтобы четвёртый параметр
          начинался с "error" (например: error, errorCode, errorSegment, errorFlags и т. п.).
          Регистр символов учитывается, т. е. имена вроде ErrorCode не распознаются как параметр
          «код ошибки». }
        inc(limit);
        interruptWithError := (limit >= 4) and
                stringStartsWith(UnicodeString('error'), ftype.getArgument(3).name);
        tree := programme.buildSyntaxTree(func) as SyntaxTree;
        if interruptWithError then begin
            argumsSize := insertArguments(ftype, (11 - limit) shl 2);
        end else begin
            argumsSize := insertArguments(ftype, (10 - limit) shl 2);
        end;
        localsSize := insertLocalVars(tree, 0);
        if func.isPureAssembler() then begin
            g.writeAssembler(stringTrim(encode(lexemes.getSourceFragment(
                    lexemes.getLine(pstart), lexemes.getChar(pstart),
                    lexemes.getLine(pfinish), lexemes.getChar(pfinish)))));
        end else begin
            g.writeInstruction('push', g.registerToString(EAX));
            g.writeInstruction('push', g.registerToString(ECX));
            g.writeInstruction('push', g.registerToString(EDX));
            g.writeInstruction('push', g.registerToString(EBX));
            g.writeInstruction('push', g.registerToString(ESI));
            g.writeInstruction('push', g.registerToString(EDI));
            g.writeInstruction('enter', g.immediateToStringShort(localsSize),
                    g.immediateToStringByte(0));
            if func.isAssembler() then begin
                g.writeAssembler(stringTrim(encode(lexemes.getSourceFragment(
                        lexemes.getLine(pstart), lexemes.getChar(pstart),
                        lexemes.getLine(pfinish), lexemes.getChar(pfinish)))));
            end else begin
                translateTree(tree);
            end;
            g.writeInstruction('leave');
            g.writeInstruction('pop', g.registerToString(EDI));
            g.writeInstruction('pop', g.registerToString(ESI));
            g.writeInstruction('pop', g.registerToString(EBX));
            g.writeInstruction('pop', g.registerToString(EDX));
            g.writeInstruction('pop', g.registerToString(ECX));
            g.writeInstruction('pop', g.registerToString(EAX));
            if interruptWithError then begin
                g.writeInstruction('add', g.registerToString(ESP), g.immediateToString(4));
            end;
            g.writeInstruction('iretd');
        end;
    end else begin
        tree := programme.buildSyntaxTree(func) as SyntaxTree;
        if functionIsEntry and (g.exitMethod = TextGenerator.EXIT_RETF) then begin
            argumsSize := insertArguments(ftype, 12);
        end else begin
            argumsSize := insertArguments(ftype, 8);
        end;
        localsSize := insertLocalVars(tree, 0);
        if func.isPureAssembler() then begin
            g.writeAssembler(stringTrim(encode(lexemes.getSourceFragment(
                    lexemes.getLine(pstart), lexemes.getChar(pstart),
                    lexemes.getLine(pfinish), lexemes.getChar(pfinish)))));
        end else begin
            functionWithSFrame := (argumsSize > 0) or (localsSize > 0);
            if functionWithSFrame then begin
                g.writeInstruction('enter', g.immediateToStringShort(localsSize),
                        g.immediateToStringByte(0));
            end;
            if func.isAssembler() then begin
                g.writeAssembler(stringTrim(encode(lexemes.getSourceFragment(
                        lexemes.getLine(pstart), lexemes.getChar(pstart),
                        lexemes.getLine(pfinish), lexemes.getChar(pfinish)))));
            end else begin
                translateTree(tree);
            end;
            if functionIsEntry then begin
                entry := programme.systemNamespace.findEntry(VARIABLE_RESULT, false);
                if entry is GlobalVariable then begin
                    g.writeInstruction('mov', g.registerToString(EAX),
                            g.memoryToString(MNONE, getEntryFullName(entry), 0));
                end;
            end else begin
                entry := nil;
            end;
            if functionWithSFrame then begin
                g.writeInstruction('leave');
            end;
            if functionIsEntry then begin
                case g.exitMethod of
                TextGenerator.EXIT_RETF: begin
                    if argumsSize > 0 then begin
                        g.writeInstruction('retf', g.immediateToString(argumsSize));
                    end else begin
                        g.writeInstruction('retf');
                    end;
                end;
                TextGenerator.EXIT_CALL: begin
                    if entry is GlobalVariable then begin
                        g.writeInstruction('push', g.registerToString(EAX));
                    end else begin
                        g.writeInstruction('pushd', g.immediateToString(0));
                    end;
                    g.writeInstruction('call', FUNCTION_EXIT);
                end;
                else
                    if argumsSize > 0 then begin
                        g.writeInstruction('ret', g.immediateToString(argumsSize));
                    end else begin
                        g.writeInstruction('ret');
                    end;
                end;
            end else begin
                if argumsSize > 0 then begin
                    g.writeInstruction('ret', g.immediateToString(argumsSize));
                end else begin
                    g.writeInstruction('ret');
                end;
            end;
        end;
    end;
    if tree <> nil then begin
        root := tree.root as SyntaxNode;
        tree.deleteChildrens(root);
        root.clearData();
    end;
    g.writeEmptyLine();
end;

procedure TranslatorBuilderOf32bitCode.translateTree(tree: SyntaxTree);
var
    i: int;
    limit: int;
    aLabelNumber: int;
    nodePosition: int;
    oldLineNumber: int;
    newLineNumber: int;
    node: BuilderNode;
    g: TextGenerator;
    lexemes: Lexer;
    stack: RegisterStack;
    sourceName: String;
begin
    g := self.generator;
    lexemes := ((tree.root as SyntaxNode).associate as GlobalFunction).owner.lexemes;
    stack := RegisterStack32bit.create(short_Array1d_create([
        EAX, ECX
    ]), short_Array1d_create([
        XMM0, XMM1, XMM2, XMM3
    ]), EBX, ESI);
    oldLineNumber := 0;
    sourceName := encode(lexemes.sourceName);
    limit := tree.getNodesWithLabelNumberCount() - 1;
    for i := 1 to limit do begin
        node := tree.getNodeWithLabelNumber(i) as BuilderNode;
        nodePosition := node.position;
        if nodePosition >= 0 then begin
            newLineNumber := lexemes.getLine(nodePosition);
            if (newLineNumber > 0) and (oldLineNumber <> newLineNumber) then begin
                g.writeCommentWithIdent(sourceName + '[' + intToString(newLineNumber) + ']: ' +
                        encode(lexemes.getSourceLine(newLineNumber)));
                oldLineNumber := newLineNumber;
            end;
        end;
        aLabelNumber := node.assignedLabelNumber;
        if aLabelNumber >= 0 then begin
            g.writeLabelShort(LABEL_LOCAL + intToString(aLabelNumber));
        end;
        translateNode(node, stack);
    end;
end;

procedure TranslatorBuilderOf32bitCode.translateNode(node: SyntaxNode; stack: RegisterStack);
var
    regInUse: boolean;
    reg1: int;
    reg2: int;
    reg3: int;
    count: int;
    buffer: int;
    nodeIndex: int;
    nodeValue: int;
    nodeLN: int;
    parentValue: int;
    parent: SyntaxNode;
    nodeAsoc: _Interface;
    nodeType: TypeDescriptor;
    mem: MemoryLocation;
    child: SyntaxNode;
    funcNode: SyntaxNode;
    funcType: TypeFunction;
    funcReturn: TypeDescriptor;
    goAlwaysTo: BuilderNode;
    goIfTrueTo: BuilderNode;
    goIfFalseTo: BuilderNode;
    g: TextGenerator;
    slbl: String;
    simm: String;
    smmb: String;
    smmw: String;
    smmd: String;
    smmt: String;
    smm: String;
    srb: String;
    srw: String;
    sr1: String;
    sr2: String;
    sr3: String;
    sAL: String;
    sCL: String;
    sDL: String;
    sAX: String;
    sDX: String;
    sEAX: String;
    sECX: String;
    sEDX: String;
    sESP: String;
    sESI: String;
    sEDI: String;
    sST0: String;
    sST1: String;
    sXMM0: String;
    sXMM4: String;
    sXMM5: String;
begin
    g := self.generator;
    sAL := g.registerToString(AL);
    sCL := g.registerToString(CL);
    sDL := g.registerToString(DL);
    sAX := g.registerToString(AX);
    sDX := g.registerToString(DX);
    sEAX := g.registerToString(EAX);
    sECX := g.registerToString(ECX);
    sEDX := g.registerToString(EDX);
    sESP := g.registerToString(ESP);
    sESI := g.registerToString(ESI);
    sEDI := g.registerToString(EDI);
    sST0 := g.registerToString(ST0);
    sST1 := g.registerToString(ST1);
    sXMM0 := g.registerToString(XMM0);
    sXMM4 := g.registerToString(XMM4);
    sXMM5 := g.registerToString(XMM5);
    nodeIndex := node.index;
    nodeValue := node.value;
    nodeLN := node.labelNumber;
    nodeAsoc := node.associate;
    nodeType := node.dataType;
    goAlwaysTo := node.goAlwaysToNode as BuilderNode;
    goIfTrueTo := node.goIfTrueToNode as BuilderNode;
    goIfFalseTo := node.goIfFalseToNode as BuilderNode;
    parent := node.parent as SyntaxNode;
    { Узлы дерева разбора, которые возвращают значения не boolean типа и
      не порождают инструкций, указаны в этом цикле: }
    while (parent <> nil) and (parent.labelNumber < 0) do begin
        buffer := parent.value;
        if (buffer <> TranslatorTreeBuilder.EXPR_QUESTION) and
                (buffer <> TranslatorTreeBuilder.EXPR_TYPE_CAST) then begin
            break;
        end;
        nodeIndex := parent.index;
        parent := parent.parent as SyntaxNode;
    end;
    if parent <> nil then begin
        parentValue := parent.value;
    end else begin
        parentValue := -1;
    end;
    case nodeValue of
    TranslatorTreeBuilder.OPERATOR_VARIABLE,
    TranslatorTreeBuilder.BLOCK_WITH: begin
        reg2 := stack.getRegAt(0);
        sr2 := g.registerToString(reg2);
        stack.popRegs(1);
        with nodeAsoc as LocalVariable do begin
            nodeType := dataType;
            mem := MemoryLocationTfasm.create(g, 0, '.' + encode(name));
        end;
        smm := mem.memoryToString(MNONE, 0);
        smmt := mem.memoryToString(MREAL, 0);
        case nodeType.kind of
        TranslatorType.KIND_BOOLEAN, TranslatorType.KIND_BYTE: begin
            reg2 := AL + (reg2 and $0f);
            sr2 := g.registerToString(reg2);
            g.writeInstruction('mov', smm, sr2);
        end;
        TranslatorType.KIND_CHAR, TranslatorType.KIND_SHORT: begin
            reg2 := AX + (reg2 and $0f);
            sr2 := g.registerToString(reg2);
            g.writeInstruction('mov', smm, sr2);
        end;
        TranslatorType.KIND_STRUCT, TranslatorType.KIND_ARRAY, TranslatorType.KIND_FUNC,
        TranslatorType.KIND_INT:
            g.writeInstruction('mov', smm, sr2);
        TranslatorType.KIND_FLOAT:
            g.writeInstruction('movss', smm, sr2);
        TranslatorType.KIND_DOUBLE:
            g.writeInstruction('movsd', smm, sr2);
        TranslatorType.KIND_REAL:
            g.writeInstruction('fstp', smmt);
        end;
    end;
    TranslatorTreeBuilder.OPERATOR_DISPOSE: begin
        stack.storeRegs(1, g);
        stack.popRegs(1);
        g.writeInstruction('call', FUNCTION_DISPOSE);
    end;
    TranslatorTreeBuilder.OPERATOR_SWITCH: begin
        translateSwitch(node, stack);
    end;
    TranslatorTreeBuilder.OPERATOR_RETURN: begin
        stack.popRegs(stack.size());
        if (goAlwaysTo <> nil) and (goAlwaysTo.labelNumber <> nodeLN + 1) then begin
            g.writeInstruction('jmp', LABEL_LOCAL + intToString(goAlwaysTo.assignedLabelNumber));
        end;
    end;
    TranslatorTreeBuilder.EXPR_VALUE_NULL: begin
        if needAllocateForPointer(parentValue, nodeIndex) then begin
            reg1 := stack.allocateGPRForPointer(g);
        end else
        if needAllocateForArray(parentValue, nodeIndex) then begin
            reg1 := stack.allocateGPRForArray(g);
        end else begin
            reg1 := stack.allocateGPR32bit(g);
        end;
        sr1 := g.registerToString(reg1);
        g.writeInstruction('xor', sr1, sr1);
    end;
    TranslatorTreeBuilder.EXPR_VALUE_BOOLEAN: begin
        if goAlwaysTo = nil then begin
            reg1 := stack.allocateGPR32bit(g);
            sr1 := g.registerToString(reg1);
            if (nodeAsoc as BooleanAsObject).booleanValue() = true then begin
                g.writeInstruction('mov', sr1, 'true');
            end else begin
                g.writeInstruction('mov', sr1, 'false');
            end;
        end else begin
            g.writeInstruction('jmp', LABEL_LOCAL + intToString(goAlwaysTo.assignedLabelNumber));
        end;
    end;
    TranslatorTreeBuilder.EXPR_VALUE_INT: begin
        if needAllocateForIndex(parentValue, nodeIndex) then begin
            reg1 := stack.allocateGPRForIndex(g);
        end else begin
            reg1 := stack.allocateGPR32bit(g);
        end;
        sr1 := g.registerToString(reg1);
        buffer := (nodeAsoc as IntegerAsObject).intValue();
        if buffer = 0 then begin
            g.writeInstruction('xor', sr1, sr1);
        end else begin
            g.writeInstruction('mov', sr1, g.immediateToStringInt(buffer));
        end;
    end;
    TranslatorTreeBuilder.EXPR_VALUE_REAL: begin
        case nodeType.kind of
        TranslatorType.KIND_FLOAT: begin
            reg1 := stack.allocateXMM(XSFLOAT, g);
            sr1 := g.registerToString(reg1);
            g.writeInstruction('movss', sr1, g.memoryToString(MNONE,
                    LABEL_POOL_FLOAT_CONTENT, programmeFloats.indexAcquire(
                    (nodeAsoc as FloatAsObject).floatValue()) * 4));
        end;
        TranslatorType.KIND_DOUBLE: begin
            reg1 := stack.allocateXMM(XSDOUBLE, g);
            sr1 := g.registerToString(reg1);
            g.writeInstruction('movsd', sr1, g.memoryToString(MNONE,
                    LABEL_POOL_DOUBLE_CONTENT, programmeDoubles.indexAcquire(
                    (nodeAsoc as DoubleAsObject).doubleValue()) * 8));
        end;
        TranslatorType.KIND_REAL: begin
            stack.allocateFPU(1, g);
            g.writeInstruction('fld', g.memoryToStringDecOffset(MREAL,
                    LABEL_POOL_REAL_CONTENT, programmeReals.indexAcquire(
                    (nodeAsoc as RealAsObject).realValue()) * 10));
        end;
        end;
    end;
    TranslatorTreeBuilder.EXPR_VALUE_STRING: begin
        if needAllocateForPointer(parentValue, nodeIndex) then begin
            reg1 := stack.allocateGPRForPointer(g);
        end else
        if needAllocateForArray(parentValue, nodeIndex) then begin
            reg1 := stack.allocateGPRForArray(g);
        end else begin
            reg1 := stack.allocateGPR32bit(g);
        end;
        sr1 := g.registerToString(reg1);
        g.writeInstruction('lea', sr1, g.memoryToString(MNONE,
                LABEL_POOL_STRING_CONTENT, programmeStrings.indexAcquire(
                (nodeAsoc as UnicodeStringAsObject).unicodeStringValue()) * 8));
    end;
    TranslatorTreeBuilder.EXPR_GLOBAL_FUNCTION: begin
        if needAllocateForPointer(parentValue, nodeIndex) then begin
            reg1 := stack.allocateGPRForPointer(g);
        end else
        if needAllocateForArray(parentValue, nodeIndex) then begin
            reg1 := stack.allocateGPRForArray(g);
        end else begin
            reg1 := stack.allocateGPR32bit(g);
        end;
        sr1 := g.registerToString(reg1);
        g.writeInstruction('lea', sr1, g.memoryToString(MNONE,
                getEntryFullName(nodeAsoc as GlobalFunction), 0));
    end;
    TranslatorTreeBuilder.EXPR_GLOBAL_VARIABLE,
    TranslatorTreeBuilder.EXPR_LOCAL_VARIABLE,
    TranslatorTreeBuilder.EXPR_ARRAY,
    TranslatorTreeBuilder.EXPR_FIELD: begin
        mem := getMemoryLocation(node, stack, false);
        smm := mem.memoryToString(MNONE, 0);
        smmb := mem.memoryToString(MBYTE, 0);
        smmw := mem.memoryToString(MWORD, 0);
        smmt := mem.memoryToString(MREAL, 0);
        case nodeType.kind of
        TranslatorType.KIND_BOOLEAN: begin
            if (goIfTrueTo <> nil) and (goIfFalseTo <> nil) then begin
                g.writeInstruction('movzx', sEDX, smmb);
                g.writeInstruction('test', sEDX, sEDX);
                stack.restoreRegs(g); { регистр флагов – без изменений }
                if goIfTrueTo.labelNumber = nodeLN + 1 then begin
                    g.writeInstruction('jz',
                            LABEL_LOCAL + intToString(goIfFalseTo.assignedLabelNumber));
                end else
                if goIfFalseTo.labelNumber = nodeLN + 1 then begin
                    g.writeInstruction('jnz',
                            LABEL_LOCAL + intToString(goIfTrueTo.assignedLabelNumber));
                end else begin
                    g.writeInstruction('jz',
                            LABEL_LOCAL + intToString(goIfFalseTo.assignedLabelNumber));
                    g.writeInstruction('jmp',
                            LABEL_LOCAL + intToString(goIfTrueTo.assignedLabelNumber));
                end;
            end else begin
                reg1 := stack.allocateGPR32bit(g);
                sr1 := g.registerToString(reg1);
                g.writeInstruction('movzx', sr1, smmb);
                stack.restoreRegs(g);
            end;
        end;
        TranslatorType.KIND_CHAR: begin
            if needAllocateForIndex(parentValue, nodeIndex) then begin
                reg1 := stack.allocateGPRForIndex(g);
            end else begin
                reg1 := stack.allocateGPR32bit(g);
            end;
            sr1 := g.registerToString(reg1);
            g.writeInstruction('movzx', sr1, smmw);
            stack.restoreRegs(g);
        end;
        TranslatorType.KIND_BYTE: begin
            if needAllocateForIndex(parentValue, nodeIndex) then begin
                reg1 := stack.allocateGPRForIndex(g);
            end else begin
                reg1 := stack.allocateGPR32bit(g);
            end;
            sr1 := g.registerToString(reg1);
            g.writeInstruction('movsx', sr1, smmb);
            stack.restoreRegs(g);
        end;
        TranslatorType.KIND_SHORT: begin
            if needAllocateForIndex(parentValue, nodeIndex) then begin
                reg1 := stack.allocateGPRForIndex(g);
            end else begin
                reg1 := stack.allocateGPR32bit(g);
            end;
            sr1 := g.registerToString(reg1);
            g.writeInstruction('movsx', sr1, smmw);
            stack.restoreRegs(g);
        end;
        TranslatorType.KIND_INT: begin
            if needAllocateForIndex(parentValue, nodeIndex) then begin
                reg1 := stack.allocateGPRForIndex(g);
            end else begin
                reg1 := stack.allocateGPR32bit(g);
            end;
            sr1 := g.registerToString(reg1);
            g.writeInstruction('mov', sr1, smm);
            stack.restoreRegs(g);
        end;
        TranslatorType.KIND_FLOAT: begin
            reg1 := stack.allocateXMM(XSFLOAT, g);
            sr1 := g.registerToString(reg1);
            g.writeInstruction('movss', sr1, smm);
            stack.restoreRegs(g);
        end;
        TranslatorType.KIND_DOUBLE: begin
            reg1 := stack.allocateXMM(XSDOUBLE, g);
            sr1 := g.registerToString(reg1);
            g.writeInstruction('movsd', sr1, smm);
            stack.restoreRegs(g);
        end;
        TranslatorType.KIND_REAL: begin
            stack.allocateFPU(1, g);
            g.writeInstruction('fld', smmt);
            stack.restoreRegs(g);
        end;
        TranslatorType.KIND_STRUCT, TranslatorType.KIND_ARRAY, TranslatorType.KIND_FUNC: begin
            if needAllocateForPointer(parentValue, nodeIndex) then begin
                reg1 := stack.allocateGPRForPointer(g);
            end else
            if needAllocateForArray(parentValue, nodeIndex) then begin
                reg1 := stack.allocateGPRForArray(g);
            end else begin
                reg1 := stack.allocateGPR32bit(g);
            end;
            sr1 := g.registerToString(reg1);
            g.writeInstruction('mov', sr1, smm);
            stack.restoreRegs(g);
        end;
        end;
    end;
    TranslatorTreeBuilder.EXPR_NEW_STRUCT: begin
        stack.storeRegs(stack.base(), g);
        count := node.getChildrensCount();
        buffer := (nodeType as TypeStructure).structureSize;
        g.writeInstruction('pushd', g.immediateToStringInt(buffer));
        g.writeInstruction('call', FUNCTION_NEW_STRUCT);
        if (count > 0) or needAllocateForPointer(parentValue, nodeIndex) then begin
            reg1 := stack.allocateGPRForPointer(g);
        end else
        if needAllocateForArray(parentValue, nodeIndex) then begin
            reg1 := stack.allocateGPRForArray(g);
        end else begin
            reg1 := stack.allocateGPR32bit(g);
        end;
        if reg1 <> EAX then begin
            sr1 := g.registerToString(reg1);
            g.writeInstruction('mov', sr1, sEAX);
        end;
        stack.restoreRegs(g);
    end;
    TranslatorTreeBuilder.EXPR_NEW_ARRAY_BY_ELEMENTS: begin
        stack.storeRegs(stack.base(), g);
        count := node.getChildrensCount();
        buffer := (nodeType as TypeArray).elementType.size;
        g.writeInstruction('pushd', g.immediateToStringInt(count));
        g.writeInstruction('pushd', g.immediateToStringInt(buffer));
        g.writeInstruction('call', FUNCTION_NEW_ARRAY);
        if (count > 0) or needAllocateForArray(parentValue, nodeIndex) then begin
            reg1 := stack.allocateGPRForArray(g);
        end else
        if needAllocateForPointer(parentValue, nodeIndex) then begin
            reg1 := stack.allocateGPRForPointer(g);
        end else begin
            reg1 := stack.allocateGPR32bit(g);
        end;
        if reg1 <> EAX then begin
            sr1 := g.registerToString(reg1);
            g.writeInstruction('mov', sr1, sEAX);
        end;
        stack.restoreRegs(g);
    end;
    TranslatorTreeBuilder.EXPR_NEW_ARRAY_BY_LENGTH: begin
        stack.storeRegs(stack.base(), g);
        stack.popRegs(1);
        buffer := (nodeType as TypeArray).elementType.size;
        g.writeInstruction('pushd', g.immediateToStringInt(buffer));
        g.writeInstruction('call', FUNCTION_NEW_ARRAY);
        if needAllocateForPointer(parentValue, nodeIndex) then begin
            reg1 := stack.allocateGPRForPointer(g);
        end else
        if needAllocateForArray(parentValue, nodeIndex) then begin
            reg1 := stack.allocateGPRForArray(g);
        end else begin
            reg1 := stack.allocateGPR32bit(g);
        end;
        if reg1 <> EAX then begin
            sr1 := g.registerToString(reg1);
            g.writeInstruction('mov', sr1, sEAX);
        end;
        stack.restoreRegs(g);
    end;
    TranslatorTreeBuilder.EXPR_FIELD_ASSIGN,
    TranslatorTreeBuilder.EXPR_ARRAY_ASSIGN: begin
        reg1 := stack.getRegAt(1);
        reg2 := stack.getRegAt(0);
        case nodeValue of
        TranslatorTreeBuilder.EXPR_FIELD_ASSIGN: begin
            sr2 := g.registerToString(reg2);
            mem := MemoryLocationTfasm.create(g, reg2, reg1,
                    getFieldFullName(nodeAsoc as StructureField));
            smm := mem.memoryToString(MNONE, 0);
            smmt := mem.memoryToString(MREAL, 0);
            stack.popRegs(1);
            case nodeType.kind of
            TranslatorType.KIND_BOOLEAN, TranslatorType.KIND_BYTE: begin
                reg2 := AL + (reg2 and $0f);
                sr2 := g.registerToString(reg2);
                g.writeInstruction('mov', smm, sr2);
            end;
            TranslatorType.KIND_CHAR, TranslatorType.KIND_SHORT: begin
                reg2 := AX + (reg2 and $0f);
                sr2 := g.registerToString(reg2);
                g.writeInstruction('mov', smm, sr2);
            end;
            TranslatorType.KIND_STRUCT, TranslatorType.KIND_ARRAY, TranslatorType.KIND_FUNC,
            TranslatorType.KIND_INT:
                g.writeInstruction('mov', smm, sr2);
            TranslatorType.KIND_FLOAT:
                g.writeInstruction('movss', smm, sr2);
            TranslatorType.KIND_DOUBLE:
                g.writeInstruction('movsd', smm, sr2);
            TranslatorType.KIND_REAL:
                g.writeInstruction('fstp', smmt);
            end;
        end;
        TranslatorTreeBuilder.EXPR_ARRAY_ASSIGN: begin
            sr1 := g.registerToString(reg1);
            sr2 := g.registerToString(reg2);
            stack.popRegs(1);
            regInUse := stack.isUsedRegister(ESI);
            if regInUse then begin
                g.writeInstruction('mov', sEDX, sESI);
            end;
            if nodeIndex = 0 then begin
                g.writeInstruction('xor', sESI, sESI);
            end else begin
                g.writeInstruction('mov', sESI, g.immediateToStringInt(nodeIndex));
            end;
            g.writeInstruction('call', FUNCTION_CHECK_ARRAY_INDEX);
            case nodeType.kind of
            TranslatorType.KIND_BOOLEAN, TranslatorType.KIND_BYTE: begin
                reg2 := AL + (reg2 and $0f);
                sr2 := g.registerToString(reg2);
                mem := MemoryLocationTfasm.create(g, reg2, reg1, ESI, 1, '');
                smm := mem.memoryToString(MNONE, 0);
                g.writeInstruction('mov', smm, sr2);
            end;
            TranslatorType.KIND_CHAR, TranslatorType.KIND_SHORT: begin
                reg2 := AX + (reg2 and $0f);
                sr2 := g.registerToString(reg2);
                mem := MemoryLocationTfasm.create(g, reg2, reg1, ESI, 2, '');
                smm := mem.memoryToString(MNONE, 0);
                g.writeInstruction('mov', smm, sr2);
            end;
            TranslatorType.KIND_STRUCT, TranslatorType.KIND_ARRAY, TranslatorType.KIND_FUNC,
            TranslatorType.KIND_INT: begin
                mem := MemoryLocationTfasm.create(g, reg2, reg1, ESI, 4, '');
                smm := mem.memoryToString(MNONE, 0);
                g.writeInstruction('mov', smm, sr2);
            end;
            TranslatorType.KIND_FLOAT: begin
                mem := MemoryLocationTfasm.create(g, reg2, reg1, ESI, 4, '');
                smm := mem.memoryToString(MNONE, 0);
                g.writeInstruction('movss', smm, sr2);
            end;
            TranslatorType.KIND_DOUBLE: begin
                mem := MemoryLocationTfasm.create(g, reg2, reg1, ESI, 8, '');
                smm := mem.memoryToString(MNONE, 0);
                g.writeInstruction('movsd', smm, sr2);
            end;
            TranslatorType.KIND_REAL: begin
                mem := MemoryLocationTfasm.create(g, reg2, reg1, ESI, '');
                smmt := mem.memoryToString(MREAL, 0);
                g.writeInstruction('imul', sESI, sESI, g.immediateToStringByte(10));
                g.writeInstruction('fstp', smmt);
            end;
            end;
            g.writeInstruction('mov', sr1, sEDI);
            if regInUse then begin
                g.writeInstruction('mov', sESI, sEDX);
            end;
        end;
        end;
        if nodeIndex = parent.getChildrensCount() - 1 then begin
            node := parent;
            nodeIndex := node.index;
            parent := node.parent as SyntaxNode;
            while (parent <> nil) and (parent.labelNumber < 0) do begin
                buffer := parent.value;
                if (buffer <> TranslatorTreeBuilder.EXPR_QUESTION) and
                        (buffer <> TranslatorTreeBuilder.EXPR_TYPE_CAST) then begin
                    break;
                end;
                nodeIndex := parent.index;
                parent := parent.parent as SyntaxNode;
            end;
            if parent <> nil then begin
                parentValue := parent.value;
            end else begin
                parentValue := -1;
            end;
            reg2 := reg1;
            sr2 := g.registerToString(reg2);
            stack.popRegs(1);
            if needAllocateForPointer(parentValue, nodeIndex) then begin
                reg1 := stack.allocateGPRForPointer(g);
            end else
            if needAllocateForArray(parentValue, nodeIndex) then begin
                reg1 := stack.allocateGPRForArray(g);
            end else begin
                reg1 := stack.allocateGPR32bit(g);
            end;
            if reg1 <> reg2 then begin
                sr1 := g.registerToString(reg1);
                g.writeInstruction('mov', sr1, sr2);
            end;
        end;
        stack.restoreRegs(g);
    end;
    TranslatorTreeBuilder.EXPR_CALL: begin
        funcNode := node.getChild(node.getChildrensCount() - 1) as SyntaxNode;
        funcType := funcNode.dataType as TypeFunction;
        funcReturn := funcType.getReturnType();
        if funcNode.value = TranslatorTreeBuilder.EXPR_GLOBAL_FUNCTION then begin
            stack.storeRegs(stack.base(), g);
            g.writeInstruction('call', getEntryFullName(funcNode.associate as GlobalFunction));
        end else begin
            reg1 := stack.getRegAt(0);
            sr1 := g.registerToString(reg1);
            stack.popRegs(1);
            stack.storeRegs(stack.base(), g);
            g.writeInstruction('call', sr1);
        end;
        stack.popRegs(funcType.getArgumentsCount());
        case TranslatorTreeBuilder.getTypeKind(nodeType) of
        TranslatorType.KIND_BOOLEAN: begin
            if (goIfTrueTo <> nil) and (goIfFalseTo <> nil) then begin
                g.writeInstruction('test', sEAX, sEAX);
                stack.restoreRegs(g); { регистр флагов – без изменений }
                if goIfTrueTo.labelNumber = nodeLN + 1 then begin
                    g.writeInstruction('jz',
                            LABEL_LOCAL + intToString(goIfFalseTo.assignedLabelNumber));
                end else
                if goIfFalseTo.labelNumber = nodeLN + 1 then begin
                    g.writeInstruction('jnz',
                            LABEL_LOCAL + intToString(goIfTrueTo.assignedLabelNumber));
                end else begin
                    g.writeInstruction('jz',
                            LABEL_LOCAL + intToString(goIfFalseTo.assignedLabelNumber));
                    g.writeInstruction('jmp',
                            LABEL_LOCAL + intToString(goIfTrueTo.assignedLabelNumber));
                end;
            end else begin
                reg1 := stack.allocateGPR32bit(g);
                if reg1 <> EAX then begin
                    sr1 := g.registerToString(reg1);
                    g.writeInstruction('mov', sr1, sEAX);
                end;
                stack.restoreRegs(g);
            end;
        end;
        TranslatorType.KIND_CHAR, TranslatorType.KIND_BYTE,
        TranslatorType.KIND_SHORT, TranslatorType.KIND_INT: begin
            if needAllocateForIndex(parentValue, nodeIndex) then begin
                reg1 := stack.allocateGPRForIndex(g);
            end else begin
                reg1 := stack.allocateGPR32bit(g);
            end;
            if reg1 <> EAX then begin
                sr1 := g.registerToString(reg1);
                g.writeInstruction('mov', sr1, sEAX);
            end;
            stack.restoreRegs(g);
        end;
        TranslatorType.KIND_FLOAT: begin
            reg1 := stack.allocateXMM(XSFLOAT, g);
            if reg1 <> XMM0 + XSFLOAT then begin
                sr1 := g.registerToString(reg1);
                g.writeInstruction('movss', sr1, sXMM0);
            end;
            stack.restoreRegs(g);
        end;
        TranslatorType.KIND_DOUBLE: begin
            reg1 := stack.allocateXMM(XSDOUBLE, g);
            if reg1 <> XMM0 + XSDOUBLE then begin
                sr1 := g.registerToString(reg1);
                g.writeInstruction('movsd', sr1, sXMM0);
            end;
            stack.restoreRegs(g);
        end;
        TranslatorType.KIND_REAL: begin
            stack.allocateFPU(1, g);
            stack.restoreRegs(g);
        end;
        TranslatorType.KIND_STRUCT, TranslatorType.KIND_ARRAY, TranslatorType.KIND_FUNC: begin
            if needAllocateForPointer(parentValue, nodeIndex) then begin
                reg1 := stack.allocateGPRForPointer(g);
            end else
            if needAllocateForArray(parentValue, nodeIndex) then begin
                reg1 := stack.allocateGPRForArray(g);
            end else begin
                reg1 := stack.allocateGPR32bit(g);
            end;
            if reg1 <> EAX then begin
                sr1 := g.registerToString(reg1);
                g.writeInstruction('mov', sr1, sEAX);
            end;
            stack.restoreRegs(g);
        end;
        else
            if (nodeType = nil) and (funcReturn <> nil) and
                    (funcReturn.kind = TranslatorType.KIND_REAL) then begin
                g.writeInstruction('ffree', sST0);
                g.writeInstruction('fincstp');
            end;
            stack.restoreRegs(g);
        end;
    end;
    TranslatorTreeBuilder.EXPR_INCR_POST,
    TranslatorTreeBuilder.EXPR_DECR_POST,
    TranslatorTreeBuilder.EXPR_INCR_PRED,
    TranslatorTreeBuilder.EXPR_DECR_PRED: begin
        regInUse := (nodeValue = TranslatorTreeBuilder.EXPR_INCR_POST) or
                (nodeValue = TranslatorTreeBuilder.EXPR_DECR_POST);
        child := node.getChild(0) as SyntaxNode;
        mem := getMemoryLocation(child, stack, false);
        smm := mem.memoryToString(MNONE, 0);
        smmb := mem.memoryToString(MBYTE, 0);
        smmw := mem.memoryToString(MWORD, 0);
        smmd := mem.memoryToString(MDWORD, 0);
        smmt := mem.memoryToString(MREAL, 0);
        case child.dataType.kind of
        TranslatorType.KIND_CHAR: begin
            if nodeType <> nil then begin
                if needAllocateForIndex(parentValue, nodeIndex) then begin
                    reg1 := stack.allocateGPRForIndex(g);
                end else begin
                    reg1 := stack.allocateGPR32bit(g);
                end;
                sr1 := g.registerToString(reg1);
                if regInUse then begin
                    g.writeInstruction('movzx', sEDX, smmw);
                    case nodeValue of
                    TranslatorTreeBuilder.EXPR_INCR_POST:
                        g.writeInstruction('inc', smmw);
                    TranslatorTreeBuilder.EXPR_DECR_POST:
                        g.writeInstruction('dec', smmw);
                    end;
                    g.writeInstruction('mov', sr1, sEDX);
                end else begin
                    case nodeValue of
                    TranslatorTreeBuilder.EXPR_INCR_PRED:
                        g.writeInstruction('inc', smmw);
                    TranslatorTreeBuilder.EXPR_DECR_PRED:
                        g.writeInstruction('dec', smmw);
                    end;
                    g.writeInstruction('movzx', sr1, smmw);
                end;
            end else begin
                case nodeValue of
                TranslatorTreeBuilder.EXPR_INCR_POST,
                TranslatorTreeBuilder.EXPR_INCR_PRED:
                    g.writeInstruction('inc', smmw);
                TranslatorTreeBuilder.EXPR_DECR_POST,
                TranslatorTreeBuilder.EXPR_DECR_PRED:
                    g.writeInstruction('dec', smmw);
                end;
            end;
        end;
        TranslatorType.KIND_BYTE: begin
            if nodeType <> nil then begin
                if needAllocateForIndex(parentValue, nodeIndex) then begin
                    reg1 := stack.allocateGPRForIndex(g);
                end else begin
                    reg1 := stack.allocateGPR32bit(g);
                end;
                sr1 := g.registerToString(reg1);
                if regInUse then begin
                    g.writeInstruction('movsx', sEDX, smmb);
                    case nodeValue of
                    TranslatorTreeBuilder.EXPR_INCR_POST:
                        g.writeInstruction('inc', smmb);
                    TranslatorTreeBuilder.EXPR_DECR_POST:
                        g.writeInstruction('dec', smmb);
                    end;
                    g.writeInstruction('mov', sr1, sEDX);
                end else begin
                    case nodeValue of
                    TranslatorTreeBuilder.EXPR_INCR_PRED:
                        g.writeInstruction('inc', smmb);
                    TranslatorTreeBuilder.EXPR_DECR_PRED:
                        g.writeInstruction('dec', smmb);
                    end;
                    g.writeInstruction('movsx', sr1, smmb);
                end;
            end else begin
                case nodeValue of
                TranslatorTreeBuilder.EXPR_INCR_POST,
                TranslatorTreeBuilder.EXPR_INCR_PRED:
                    g.writeInstruction('inc', smmb);
                TranslatorTreeBuilder.EXPR_DECR_POST,
                TranslatorTreeBuilder.EXPR_DECR_PRED:
                    g.writeInstruction('dec', smmb);
                end;
            end;
        end;
        TranslatorType.KIND_SHORT: begin
            if nodeType <> nil then begin
                if needAllocateForIndex(parentValue, nodeIndex) then begin
                    reg1 := stack.allocateGPRForIndex(g);
                end else begin
                    reg1 := stack.allocateGPR32bit(g);
                end;
                sr1 := g.registerToString(reg1);
                if regInUse then begin
                    g.writeInstruction('movsx', sEDX, smmw);
                    case nodeValue of
                    TranslatorTreeBuilder.EXPR_INCR_POST:
                        g.writeInstruction('inc', smmw);
                    TranslatorTreeBuilder.EXPR_DECR_POST:
                        g.writeInstruction('dec', smmw);
                    end;
                    g.writeInstruction('mov', sr1, sEDX);
                end else begin
                    case nodeValue of
                    TranslatorTreeBuilder.EXPR_INCR_PRED:
                        g.writeInstruction('inc', smmw);
                    TranslatorTreeBuilder.EXPR_DECR_PRED:
                        g.writeInstruction('dec', smmw);
                    end;
                    g.writeInstruction('movsx', sr1, smmw);
                end;
            end else begin
                case nodeValue of
                TranslatorTreeBuilder.EXPR_INCR_POST,
                TranslatorTreeBuilder.EXPR_INCR_PRED:
                    g.writeInstruction('inc', smmw);
                TranslatorTreeBuilder.EXPR_DECR_POST,
                TranslatorTreeBuilder.EXPR_DECR_PRED:
                    g.writeInstruction('dec', smmw);
                end;
            end;
        end;
        TranslatorType.KIND_INT: begin
            if nodeType <> nil then begin
                if needAllocateForIndex(parentValue, nodeIndex) then begin
                    reg1 := stack.allocateGPRForIndex(g);
                end else begin
                    reg1 := stack.allocateGPR32bit(g);
                end;
                sr1 := g.registerToString(reg1);
                if regInUse then begin
                    g.writeInstruction('mov', sEDX, smm);
                    case nodeValue of
                    TranslatorTreeBuilder.EXPR_INCR_POST:
                        g.writeInstruction('inc', smmd);
                    TranslatorTreeBuilder.EXPR_DECR_POST:
                        g.writeInstruction('dec', smmd);
                    end;
                    g.writeInstruction('mov', sr1, sEDX);
                end else begin
                    case nodeValue of
                    TranslatorTreeBuilder.EXPR_INCR_PRED:
                        g.writeInstruction('inc', smmd);
                    TranslatorTreeBuilder.EXPR_DECR_PRED:
                        g.writeInstruction('dec', smmd);
                    end;
                    g.writeInstruction('mov', sr1, smm);
                end;
            end else begin
                case nodeValue of
                TranslatorTreeBuilder.EXPR_INCR_POST,
                TranslatorTreeBuilder.EXPR_INCR_PRED:
                    g.writeInstruction('inc', smmd);
                TranslatorTreeBuilder.EXPR_DECR_POST,
                TranslatorTreeBuilder.EXPR_DECR_PRED:
                    g.writeInstruction('dec', smmd);
                end;
            end;
        end;
        TranslatorType.KIND_FLOAT: begin
            if nodeType <> nil then begin
                reg1 := stack.allocateXMM(XSFLOAT, g);
                sr1 := g.registerToString(reg1);
                g.writeInstruction('movss', sr1, smm);
                if regInUse then begin
                    g.writeInstruction('movss', sXMM4, sr1);
                    g.writeInstruction('movss', sXMM5, g.memoryToString(MNONE,
                            LABEL_POOL_FLOAT_CONTENT, programmeFloats.indexAcquire(1) * 4));
                    case nodeValue of
                    TranslatorTreeBuilder.EXPR_INCR_POST:
                        g.writeInstruction('addss', sXMM4, sXMM5);
                    TranslatorTreeBuilder.EXPR_DECR_POST:
                        g.writeInstruction('subss', sXMM4, sXMM5);
                    end;
                    g.writeInstruction('movss', smm, sXMM4);
                end else begin
                    g.writeInstruction('movss', sXMM4, g.memoryToString(MNONE,
                            LABEL_POOL_FLOAT_CONTENT, programmeFloats.indexAcquire(1) * 4));
                    case nodeValue of
                    TranslatorTreeBuilder.EXPR_INCR_PRED:
                        g.writeInstruction('addss', sr1, sXMM4);
                    TranslatorTreeBuilder.EXPR_DECR_PRED:
                        g.writeInstruction('subss', sr1, sXMM4);
                    end;
                    g.writeInstruction('movss', smm, sr1);
                end;
            end else begin
                g.writeInstruction('movss', sXMM4, smm);
                g.writeInstruction('movss', sXMM5, g.memoryToString(MNONE,
                        LABEL_POOL_FLOAT_CONTENT, programmeFloats.indexAcquire(1) * 4));
                case nodeValue of
                TranslatorTreeBuilder.EXPR_INCR_POST,
                TranslatorTreeBuilder.EXPR_INCR_PRED:
                    g.writeInstruction('addss', sXMM4, sXMM5);
                TranslatorTreeBuilder.EXPR_DECR_POST,
                TranslatorTreeBuilder.EXPR_DECR_PRED:
                    g.writeInstruction('subss', sXMM4, sXMM5);
                end;
                g.writeInstruction('movss', smm, sXMM4);
            end;
        end;
        TranslatorType.KIND_DOUBLE: begin
            if nodeType <> nil then begin
                reg1 := stack.allocateXMM(XSDOUBLE, g);
                sr1 := g.registerToString(reg1);
                g.writeInstruction('movsd', sr1, smm);
                if regInUse then begin
                    g.writeInstruction('movsd', sXMM4, sr1);
                    g.writeInstruction('movsd', sXMM5, g.memoryToString(MNONE,
                            LABEL_POOL_DOUBLE_CONTENT, programmeDoubles.indexAcquire(1) * 8));
                    case nodeValue of
                    TranslatorTreeBuilder.EXPR_INCR_POST:
                        g.writeInstruction('addsd', sXMM4, sXMM5);
                    TranslatorTreeBuilder.EXPR_DECR_POST:
                        g.writeInstruction('subsd', sXMM4, sXMM5);
                    end;
                    g.writeInstruction('movsd', smm, sXMM4);
                end else begin
                    g.writeInstruction('movsd', sXMM4, g.memoryToString(MNONE,
                            LABEL_POOL_DOUBLE_CONTENT, programmeDoubles.indexAcquire(1) * 8));
                    case nodeValue of
                    TranslatorTreeBuilder.EXPR_INCR_PRED:
                        g.writeInstruction('addsd', sr1, sXMM4);
                    TranslatorTreeBuilder.EXPR_DECR_PRED:
                        g.writeInstruction('subsd', sr1, sXMM4);
                    end;
                    g.writeInstruction('movsd', smm, sr1);
                end;
            end else begin
                g.writeInstruction('movsd', sXMM4, smm);
                g.writeInstruction('movsd', sXMM5, g.memoryToString(MNONE,
                        LABEL_POOL_DOUBLE_CONTENT, programmeDoubles.indexAcquire(1) * 8));
                case nodeValue of
                TranslatorTreeBuilder.EXPR_INCR_POST,
                TranslatorTreeBuilder.EXPR_INCR_PRED:
                    g.writeInstruction('addsd', sXMM4, sXMM5);
                TranslatorTreeBuilder.EXPR_DECR_POST,
                TranslatorTreeBuilder.EXPR_DECR_PRED:
                    g.writeInstruction('subsd', sXMM4, sXMM5);
                end;
                g.writeInstruction('movsd', smm, sXMM4);
            end;
        end;
        TranslatorType.KIND_REAL: begin
            if nodeType <> nil then begin
                if regInUse then begin
                    stack.allocateFPU(2, g);
                    stack.popRegs(1);
                    g.writeInstruction('fld', smmt);
                    g.writeInstruction('fld', sST0);
                    case nodeValue of
                    TranslatorTreeBuilder.EXPR_INCR_POST:
                        g.writeInstruction('fadd', g.memoryToString(MFLOAT,
                                LABEL_POOL_FLOAT_CONTENT, programmeFloats.indexAcquire(1) * 4));
                    TranslatorTreeBuilder.EXPR_DECR_POST:
                        g.writeInstruction('fsub', g.memoryToString(MFLOAT,
                                LABEL_POOL_FLOAT_CONTENT, programmeFloats.indexAcquire(1) * 4));
                    end;
                    g.writeInstruction('fstp', smmt);
                end else begin
                    stack.allocateFPU(1, g);
                    g.writeInstruction('fld', smmt);
                    case nodeValue of
                    TranslatorTreeBuilder.EXPR_INCR_PRED:
                        g.writeInstruction('fadd', g.memoryToString(MFLOAT,
                                LABEL_POOL_FLOAT_CONTENT, programmeFloats.indexAcquire(1) * 4));
                    TranslatorTreeBuilder.EXPR_DECR_PRED:
                        g.writeInstruction('fsub', g.memoryToString(MFLOAT,
                                LABEL_POOL_FLOAT_CONTENT, programmeFloats.indexAcquire(1) * 4));
                    end;
                    g.writeInstruction('fstp', smmt);
                    g.writeInstruction('fld', smmt);
                end;
            end else begin
                stack.allocateFPU(1, g);
                stack.popRegs(1);
                g.writeInstruction('fld', smmt);
                case nodeValue of
                TranslatorTreeBuilder.EXPR_INCR_POST,
                TranslatorTreeBuilder.EXPR_INCR_PRED:
                    g.writeInstruction('fadd', g.memoryToString(MFLOAT,
                            LABEL_POOL_FLOAT_CONTENT, programmeFloats.indexAcquire(1) * 4));
                TranslatorTreeBuilder.EXPR_DECR_POST,
                TranslatorTreeBuilder.EXPR_DECR_PRED:
                    g.writeInstruction('fsub', g.memoryToString(MFLOAT,
                            LABEL_POOL_FLOAT_CONTENT, programmeFloats.indexAcquire(1) * 4));
                end;
                g.writeInstruction('fstp', smmt);
            end;
        end;
        end;
        stack.restoreRegs(g);
    end;
    TranslatorTreeBuilder.EXPR_TYPE_CAST: begin
        reg2 := stack.getRegAt(0);
        sr2 := g.registerToString(reg2);
        stack.popRegs(1);
        case (node.getChild(0) as SyntaxNode).dataType.kind of
        TranslatorType.KIND_CHAR, TranslatorType.KIND_BYTE, TranslatorType.KIND_SHORT,
        TranslatorType.KIND_INT: {%region исходный тип данных – int}
            case nodeType.kind of
            TranslatorType.KIND_CHAR: begin
                if needAllocateForIndex(parentValue, nodeIndex) then begin
                    reg1 := stack.allocateGPRForIndex(g);
                end else begin
                    reg1 := stack.allocateGPR32bit(g);
                end;
                sr1 := g.registerToString(reg1);
                srw := g.registerToString(AX + (reg2 and $0f));
                g.writeInstruction('movzx', sr1, srw);
            end;
            TranslatorType.KIND_BYTE: begin
                if needAllocateForIndex(parentValue, nodeIndex) then begin
                    reg1 := stack.allocateGPRForIndex(g);
                end else begin
                    reg1 := stack.allocateGPR32bit(g);
                end;
                sr1 := g.registerToString(reg1);
                srb := g.registerToString(AL + (reg2 and $0f));
                g.writeInstruction('movsx', sr1, srb);
            end;
            TranslatorType.KIND_SHORT: begin
                if needAllocateForIndex(parentValue, nodeIndex) then begin
                    reg1 := stack.allocateGPRForIndex(g);
                end else begin
                    reg1 := stack.allocateGPR32bit(g);
                end;
                sr1 := g.registerToString(reg1);
                srw := g.registerToString(AX + (reg2 and $0f));
                g.writeInstruction('movsx', sr1, srw);
            end;
            TranslatorType.KIND_FLOAT: begin
                reg1 := stack.allocateXMM(XSFLOAT, g);
                sr1 := g.registerToString(reg1);
                g.writeInstruction('cvtsi2ss', sr1, sr2);
            end;
            TranslatorType.KIND_DOUBLE: begin
                reg1 := stack.allocateXMM(XSDOUBLE, g);
                sr1 := g.registerToString(reg1);
                g.writeInstruction('cvtsi2sd', sr1, sr2);
            end;
            TranslatorType.KIND_REAL: begin
                stack.allocateFPU(1, g);
                g.writeInstruction('push', sr2);
                g.writeInstruction('fild', g.memoryToString(MINT, ESP, 0));
                g.writeInstruction('lea', sESP, g.memoryToString(MNONE, ESP, 4));
            end;
            end;
        {%endregion}
        TranslatorType.KIND_FLOAT: {%region исходный тип данных – float}
            case nodeType.kind of
            TranslatorType.KIND_CHAR: begin
                if needAllocateForIndex(parentValue, nodeIndex) then begin
                    reg1 := stack.allocateGPRForIndex(g);
                end else begin
                    reg1 := stack.allocateGPR32bit(g);
                end;
                sr1 := g.registerToString(reg1);
                g.writeInstruction('movss', sXMM4, sr2);
                g.writeInstruction('call', FUNCTION_FLOAT_TO_INT);
                g.writeInstruction('movzx', sr1, sDX);
            end;
            TranslatorType.KIND_BYTE: begin
                if needAllocateForIndex(parentValue, nodeIndex) then begin
                    reg1 := stack.allocateGPRForIndex(g);
                end else begin
                    reg1 := stack.allocateGPR32bit(g);
                end;
                sr1 := g.registerToString(reg1);
                g.writeInstruction('movss', sXMM4, sr2);
                g.writeInstruction('call', FUNCTION_FLOAT_TO_INT);
                g.writeInstruction('movsx', sr1, sDL);
            end;
            TranslatorType.KIND_SHORT: begin
                if needAllocateForIndex(parentValue, nodeIndex) then begin
                    reg1 := stack.allocateGPRForIndex(g);
                end else begin
                    reg1 := stack.allocateGPR32bit(g);
                end;
                sr1 := g.registerToString(reg1);
                g.writeInstruction('movss', sXMM4, sr2);
                g.writeInstruction('call', FUNCTION_FLOAT_TO_INT);
                g.writeInstruction('movsx', sr1, sDX);
            end;
            TranslatorType.KIND_INT: begin
                if needAllocateForIndex(parentValue, nodeIndex) then begin
                    reg1 := stack.allocateGPRForIndex(g);
                end else begin
                    reg1 := stack.allocateGPR32bit(g);
                end;
                sr1 := g.registerToString(reg1);
                g.writeInstruction('movss', sXMM4, sr2);
                g.writeInstruction('call', FUNCTION_FLOAT_TO_INT);
                g.writeInstruction('mov', sr1, sEDX);
            end;
            TranslatorType.KIND_DOUBLE: begin
                reg1 := stack.allocateXMM(XSDOUBLE, g);
                sr1 := g.registerToString(reg1);
                g.writeInstruction('cvtss2sd', sr1, sr2);
            end;
            TranslatorType.KIND_REAL: begin
                stack.allocateFPU(1, g);
                g.writeInstruction('lea', sESP, g.memoryToString(MNONE, ESP, -4));
                g.writeInstruction('movss', g.memoryToString(MNONE, ESP, 0), sr2);
                g.writeInstruction('fld', g.memoryToString(MFLOAT, ESP, 0));
                g.writeInstruction('lea', sESP, g.memoryToString(MNONE, ESP, 4));
            end;
            end;
        {%endregion}
        TranslatorType.KIND_DOUBLE: {%region исходный тип данных – double}
            case nodeType.kind of
            TranslatorType.KIND_CHAR: begin
                if needAllocateForIndex(parentValue, nodeIndex) then begin
                    reg1 := stack.allocateGPRForIndex(g);
                end else begin
                    reg1 := stack.allocateGPR32bit(g);
                end;
                sr1 := g.registerToString(reg1);
                g.writeInstruction('movsd', sXMM4, sr2);
                g.writeInstruction('call', FUNCTION_DOUBLE_TO_INT);
                g.writeInstruction('movzx', sr1, sDX);
            end;
            TranslatorType.KIND_BYTE: begin
                if needAllocateForIndex(parentValue, nodeIndex) then begin
                    reg1 := stack.allocateGPRForIndex(g);
                end else begin
                    reg1 := stack.allocateGPR32bit(g);
                end;
                sr1 := g.registerToString(reg1);
                g.writeInstruction('movsd', sXMM4, sr2);
                g.writeInstruction('call', FUNCTION_DOUBLE_TO_INT);
                g.writeInstruction('movsx', sr1, sDL);
            end;
            TranslatorType.KIND_SHORT: begin
                if needAllocateForIndex(parentValue, nodeIndex) then begin
                    reg1 := stack.allocateGPRForIndex(g);
                end else begin
                    reg1 := stack.allocateGPR32bit(g);
                end;
                sr1 := g.registerToString(reg1);
                g.writeInstruction('movsd', sXMM4, sr2);
                g.writeInstruction('call', FUNCTION_DOUBLE_TO_INT);
                g.writeInstruction('movsx', sr1, sDX);
            end;
            TranslatorType.KIND_INT: begin
                if needAllocateForIndex(parentValue, nodeIndex) then begin
                    reg1 := stack.allocateGPRForIndex(g);
                end else begin
                    reg1 := stack.allocateGPR32bit(g);
                end;
                sr1 := g.registerToString(reg1);
                g.writeInstruction('movsd', sXMM4, sr2);
                g.writeInstruction('call', FUNCTION_DOUBLE_TO_INT);
                g.writeInstruction('mov', sr1, sEDX);
            end;
            TranslatorType.KIND_FLOAT: begin
                reg1 := stack.allocateXMM(XSFLOAT, g);
                sr1 := g.registerToString(reg1);
                g.writeInstruction('cvtsd2ss', sr1, sr2);
            end;
            TranslatorType.KIND_REAL: begin
                stack.allocateFPU(1, g);
                g.writeInstruction('lea', sESP, g.memoryToString(MNONE, ESP, -8));
                g.writeInstruction('movsd', g.memoryToString(MNONE, ESP, 0), sr2);
                g.writeInstruction('fld', g.memoryToString(MDOUBLE, ESP, 0));
                g.writeInstruction('lea', sESP, g.memoryToString(MNONE, ESP, 8));
            end;
            end;
        {%endregion}
        TranslatorType.KIND_REAL: {%region исходный тип данных – real}
            case nodeType.kind of
            TranslatorType.KIND_CHAR: begin
                if needAllocateForIndex(parentValue, nodeIndex) then begin
                    reg1 := stack.allocateGPRForIndex(g);
                end else begin
                    reg1 := stack.allocateGPR32bit(g);
                end;
                sr1 := g.registerToString(reg1);
                g.writeInstruction('call', FUNCTION_REAL_TO_INT);
                g.writeInstruction('movzx', sr1, sDX);
            end;
            TranslatorType.KIND_BYTE: begin
                if needAllocateForIndex(parentValue, nodeIndex) then begin
                    reg1 := stack.allocateGPRForIndex(g);
                end else begin
                    reg1 := stack.allocateGPR32bit(g);
                end;
                sr1 := g.registerToString(reg1);
                g.writeInstruction('call', FUNCTION_REAL_TO_INT);
                g.writeInstruction('movsx', sr1, sDL);
            end;
            TranslatorType.KIND_SHORT: begin
                if needAllocateForIndex(parentValue, nodeIndex) then begin
                    reg1 := stack.allocateGPRForIndex(g);
                end else begin
                    reg1 := stack.allocateGPR32bit(g);
                end;
                sr1 := g.registerToString(reg1);
                g.writeInstruction('call', FUNCTION_REAL_TO_INT);
                g.writeInstruction('movsx', sr1, sDX);
            end;
            TranslatorType.KIND_INT: begin
                if needAllocateForIndex(parentValue, nodeIndex) then begin
                    reg1 := stack.allocateGPRForIndex(g);
                end else begin
                    reg1 := stack.allocateGPR32bit(g);
                end;
                sr1 := g.registerToString(reg1);
                g.writeInstruction('call', FUNCTION_REAL_TO_INT);
                g.writeInstruction('mov', sr1, sEDX);
            end;
            TranslatorType.KIND_FLOAT: begin
                reg1 := stack.allocateXMM(XSFLOAT, g);
                sr1 := g.registerToString(reg1);
                g.writeInstruction('lea', sESP, g.memoryToString(MNONE, ESP, -4));
                g.writeInstruction('fstp', g.memoryToString(MFLOAT, ESP, 0));
                g.writeInstruction('movss', sr1, g.memoryToString(MNONE, ESP, 0));
                g.writeInstruction('lea', sESP, g.memoryToString(MNONE, ESP, 4));
            end;
            TranslatorType.KIND_DOUBLE: begin
                reg1 := stack.allocateXMM(XSDOUBLE, g);
                sr1 := g.registerToString(reg1);
                g.writeInstruction('lea', sESP, g.memoryToString(MNONE, ESP, -8));
                g.writeInstruction('fstp', g.memoryToString(MDOUBLE, ESP, 0));
                g.writeInstruction('movsd', sr1, g.memoryToString(MNONE, ESP, 0));
                g.writeInstruction('lea', sESP, g.memoryToString(MNONE, ESP, 8));
            end;
            end;
        {%endregion}
        end;
        stack.restoreRegs(g);
    end;
    TranslatorTreeBuilder.EXPR_SNOTB: begin
        reg2 := stack.getRegAt(0);
        stack.popRegs(1);
        if needAllocateForIndex(parentValue, nodeIndex) then begin
            reg1 := stack.allocateGPRForIndex(g);
        end else begin
            reg1 := stack.allocateGPR32bit(g);
        end;
        sr1 := g.registerToString(reg1);
        if reg1 <> reg2 then begin
            sr2 := g.registerToString(reg2);
            g.writeInstruction('mov', sr1, sr2);
        end;
        g.writeInstruction('not', sr1);
        stack.restoreRegs(g);
    end;
    TranslatorTreeBuilder.EXPR_SNEG: begin
        reg2 := stack.getRegAt(0);
        sr2 := g.registerToString(reg2);
        case (node.getChild(0) as SyntaxNode).dataType.kind of
        TranslatorType.KIND_INT: begin
            stack.popRegs(1);
            if needAllocateForIndex(parentValue, nodeIndex) then begin
                reg1 := stack.allocateGPRForIndex(g);
            end else begin
                reg1 := stack.allocateGPR32bit(g);
            end;
            sr1 := g.registerToString(reg1);
            if reg1 <> reg2 then begin
                g.writeInstruction('mov', sr1, sr2);
            end;
            g.writeInstruction('neg', sr1);
            stack.restoreRegs(g);
        end;
        TranslatorType.KIND_FLOAT: begin
            g.writeInstruction('movss', sXMM4, sr2);
            g.writeInstruction('movss', sr2, g.memoryToString(MNONE,
                    LABEL_POOL_FLOAT_CONTENT, programmeFloats.indexAcquire(0) * 4));
            g.writeInstruction('subss', sr2, sXMM4);
        end;
        TranslatorType.KIND_DOUBLE: begin
            g.writeInstruction('movsd', sXMM4, sr2);
            g.writeInstruction('movsd', sr2, g.memoryToString(MNONE,
                    LABEL_POOL_DOUBLE_CONTENT, programmeDoubles.indexAcquire(0) * 8));
            g.writeInstruction('subsd', sr2, sXMM4);
        end;
        TranslatorType.KIND_REAL: begin
            g.writeInstruction('fchs');
        end;
        end;
    end;
    TranslatorTreeBuilder.EXPR_SADD,
    TranslatorTreeBuilder.EXPR_SSUB,
    TranslatorTreeBuilder.EXPR_SMULL: begin
        reg2 := stack.getRegAt(1);
        reg3 := stack.getRegAt(0);
        sr2 := g.registerToString(reg2);
        sr3 := g.registerToString(reg3);
        stack.popRegs(1);
        case (node.getChild(0) as SyntaxNode).dataType.kind of
        TranslatorType.KIND_INT: begin
            stack.popRegs(1);
            if needAllocateForIndex(parentValue, nodeIndex) then begin
                reg1 := stack.allocateGPRForIndex(g);
            end else begin
                reg1 := stack.allocateGPR32bit(g);
            end;
            sr1 := g.registerToString(reg1);
            if reg1 <> reg2 then begin
                g.writeInstruction('mov', sr1, sr2);
            end;
            case nodeValue of
            TranslatorTreeBuilder.EXPR_SADD:
                g.writeInstruction('add', sr1, sr3);
            TranslatorTreeBuilder.EXPR_SSUB:
                g.writeInstruction('sub', sr1, sr3);
            TranslatorTreeBuilder.EXPR_SMULL:
                g.writeInstruction('imul', sr1, sr3);
            end;
        end;
        TranslatorType.KIND_FLOAT: begin
            case nodeValue of
            TranslatorTreeBuilder.EXPR_SADD:
                g.writeInstruction('addss', sr2, sr3);
            TranslatorTreeBuilder.EXPR_SSUB:
                g.writeInstruction('subss', sr2, sr3);
            TranslatorTreeBuilder.EXPR_SMULL:
                g.writeInstruction('mulss', sr2, sr3);
            end;
        end;
        TranslatorType.KIND_DOUBLE: begin
            case nodeValue of
            TranslatorTreeBuilder.EXPR_SADD:
                g.writeInstruction('addsd', sr2, sr3);
            TranslatorTreeBuilder.EXPR_SSUB:
                g.writeInstruction('subsd', sr2, sr3);
            TranslatorTreeBuilder.EXPR_SMULL:
                g.writeInstruction('mulsd', sr2, sr3);
            end;
        end;
        TranslatorType.KIND_REAL: begin
            case nodeValue of
            TranslatorTreeBuilder.EXPR_SADD:
                g.writeInstruction('faddp');
            TranslatorTreeBuilder.EXPR_SSUB:
                g.writeInstruction('fsubp');
            TranslatorTreeBuilder.EXPR_SMULL:
                g.writeInstruction('fmulp');
            end;
        end;
        end;
        stack.restoreRegs(g);
    end;
    TranslatorTreeBuilder.EXPR_SDIVS,
    TranslatorTreeBuilder.EXPR_SDIVU: begin
        reg2 := stack.getRegAt(1);
        reg3 := stack.getRegAt(0);
        sr2 := g.registerToString(reg2);
        sr3 := g.registerToString(reg3);
        stack.popRegs(1);
        case (node.getChild(0) as SyntaxNode).dataType.kind of
        TranslatorType.KIND_INT: begin
            stack.popRegs(1);
            regInUse := stack.isUsedRegister(EAX);
            if needAllocateForIndex(parentValue, nodeIndex) then begin
                reg1 := stack.allocateGPRForIndex(g);
            end else begin
                reg1 := stack.allocateGPR32bit(g);
            end;
            sr1 := g.registerToString(reg1);
            if reg3 = EAX then begin
                g.writeInstruction('xchg', sr3, sr2);
                case nodeValue of
                TranslatorTreeBuilder.EXPR_SDIVS: begin
                    g.writeInstruction('cdq');
                    g.writeInstruction('idiv', sr2);
                end;
                TranslatorTreeBuilder.EXPR_SDIVU: begin
                    g.writeInstruction('xor', sEDX, sEDX);
                    g.writeInstruction('div', sr2);
                end;
                end;
                if reg1 <> EAX then begin
                    g.writeInstruction('mov', sr1, sEAX);
                end;
            end else begin
                if regInUse then begin
                    g.writeInstruction('mov', sEDI, sEAX);
                end;
                if reg2 <> EAX then begin
                    g.writeInstruction('mov', sEAX, sr2);
                end;
                case nodeValue of
                TranslatorTreeBuilder.EXPR_SDIVS: begin
                    g.writeInstruction('cdq');
                    g.writeInstruction('idiv', sr3);
                end;
                TranslatorTreeBuilder.EXPR_SDIVU: begin
                    g.writeInstruction('xor', sDX, sDX);
                    g.writeInstruction('div', sr3);
                end;
                end;
                if reg1 <> EAX then begin
                    g.writeInstruction('mov', sr1, sEAX);
                end;
                if regInUse then begin
                    g.writeInstruction('mov', sEAX, sEDI);
                end;
            end;
        end;
        TranslatorType.KIND_FLOAT: begin
            g.writeInstruction('divss', sr2, sr3);
        end;
        TranslatorType.KIND_DOUBLE: begin
            g.writeInstruction('divsd', sr2, sr3);
        end;
        TranslatorType.KIND_REAL: begin
            g.writeInstruction('fdivp');
        end;
        end;
        stack.restoreRegs(g);
    end;
    TranslatorTreeBuilder.EXPR_SREMS,
    TranslatorTreeBuilder.EXPR_SREMU: begin
        reg2 := stack.getRegAt(1);
        reg3 := stack.getRegAt(0);
        sr2 := g.registerToString(reg2);
        sr3 := g.registerToString(reg3);
        stack.popRegs(1);
        case (node.getChild(0) as SyntaxNode).dataType.kind of
        TranslatorType.KIND_INT: begin
            stack.popRegs(1);
            regInUse := stack.isUsedRegister(EAX);
            if needAllocateForIndex(parentValue, nodeIndex) then begin
                reg1 := stack.allocateGPRForIndex(g);
            end else begin
                reg1 := stack.allocateGPR32bit(g);
            end;
            sr1 := g.registerToString(reg1);
            if reg3 = EAX then begin
                g.writeInstruction('xchg', sr3, sr2);
                case nodeValue of
                TranslatorTreeBuilder.EXPR_SREMS: begin
                    g.writeInstruction('cdq');
                    g.writeInstruction('idiv', sr2);
                end;
                TranslatorTreeBuilder.EXPR_SREMU: begin
                    g.writeInstruction('xor', sEDX, sEDX);
                    g.writeInstruction('div', sr2);
                end;
                end;
                if reg1 <> EDX then begin
                    g.writeInstruction('mov', sr1, sEDX);
                end;
            end else begin
                if regInUse then begin
                    g.writeInstruction('mov', sEDI, sEAX);
                end;
                if reg2 <> EAX then begin
                    g.writeInstruction('mov', sEAX, sr2);
                end;
                case nodeValue of
                TranslatorTreeBuilder.EXPR_SREMS: begin
                    g.writeInstruction('cdq');
                    g.writeInstruction('idiv', sr3);
                end;
                TranslatorTreeBuilder.EXPR_SREMU: begin
                    g.writeInstruction('xor', sEDX, sEDX);
                    g.writeInstruction('div', sr3);
                end;
                end;
                if reg1 <> EDX then begin
                    g.writeInstruction('mov', sr1, sEDX);
                end;
                if regInUse then begin
                    g.writeInstruction('mov', sEAX, sEDI);
                end;
            end;
        end;
        TranslatorType.KIND_REAL: begin
            regInUse := stack.isUsedRegister(EAX);
            if regInUse then begin
                g.writeInstruction('mov', sEDX, sEAX);
            end;
            g.writeInstruction('fxch');
            g.writeLabelShort(LABEL_ANONYMOUS);
            g.writeInstruction('fprem');
            g.writeInstruction('fnstsw', sAX);
            g.writeInstruction('test', sEAX, g.immediateToStringShort($0400));
            g.writeInstruction('jnz', LABEL_PRECEDING);
            g.writeInstruction('fstp', sST1);
            if regInUse then begin
                g.writeInstruction('mov', sEAX, sEDX);
            end;
        end;
        end;
        stack.restoreRegs(g);
    end;
    TranslatorTreeBuilder.EXPR_SSLL,
    TranslatorTreeBuilder.EXPR_SSRA,
    TranslatorTreeBuilder.EXPR_SSRL: begin
        child := node.getChild(1) as SyntaxNode;
        if child.value <> TranslatorTreeBuilder.EXPR_VALUE_INT then begin
            reg2 := stack.getRegAt(1);
            reg3 := stack.getRegAt(0);
            stack.popRegs(2);
            regInUse := stack.isUsedRegister(ECX);
            if needAllocateForIndex(parentValue, nodeIndex) then begin
                reg1 := stack.allocateGPRForIndex(g);
            end else begin
                reg1 := stack.allocateGPR32bit(g);
            end;
            sr1 := g.registerToString(reg1);
            sr2 := g.registerToString(reg2);
            sr3 := g.registerToString(reg3);
            if reg2 = ECX then begin
                g.writeInstruction('xchg', sr3, sr2);
                case nodeValue of
                TranslatorTreeBuilder.EXPR_SSLL:
                    g.writeInstruction('shl', sr3, sCL);
                TranslatorTreeBuilder.EXPR_SSRA:
                    g.writeInstruction('sar', sr3, sCL);
                TranslatorTreeBuilder.EXPR_SSRL:
                    g.writeInstruction('shr', sr3, sCL);
                end;
                if reg1 <> reg3 then begin
                    g.writeInstruction('mov', sr1, sr3);
                end;
            end else begin
                if regInUse then begin
                    g.writeInstruction('mov', sEDX, sECX);
                end;
                if reg3 <> ECX then begin
                    g.writeInstruction('mov', sECX, sr3);
                end;
                case nodeValue of
                TranslatorTreeBuilder.EXPR_SSLL:
                    g.writeInstruction('shl', sr2, sCL);
                TranslatorTreeBuilder.EXPR_SSRA:
                    g.writeInstruction('sar', sr2, sCL);
                TranslatorTreeBuilder.EXPR_SSRL:
                    g.writeInstruction('shr', sr2, sCL);
                end;
                if reg1 <> reg2 then begin
                    g.writeInstruction('mov', sr1, sr2);
                end;
                if regInUse then begin
                    g.writeInstruction('mov', sECX, sEDX);
                end;
            end;
        end else begin
            reg2 := stack.getRegAt(0);
            buffer := (child.associate as IntegerAsObject).byteValue();
            simm := g.immediateToStringByte(buffer);
            stack.popRegs(1);
            if needAllocateForIndex(parentValue, nodeIndex) then begin
                reg1 := stack.allocateGPRForIndex(g);
            end else begin
                reg1 := stack.allocateGPR32bit(g);
            end;
            sr1 := g.registerToString(reg1);
            sr2 := g.registerToString(reg2);
            case nodeValue of
            TranslatorTreeBuilder.EXPR_SSLL:
                g.writeInstruction('shl', sr2, simm);
            TranslatorTreeBuilder.EXPR_SSRA:
                g.writeInstruction('sar', sr2, simm);
            TranslatorTreeBuilder.EXPR_SSRL:
                g.writeInstruction('shr', sr2, simm);
            end;
            if reg1 <> reg2 then begin
                g.writeInstruction('mov', sr1, sr2);
            end;
        end;
        stack.restoreRegs(g);
    end;
    TranslatorTreeBuilder.EXPR_SGT,
    TranslatorTreeBuilder.EXPR_SGE,
    TranslatorTreeBuilder.EXPR_SLT,
    TranslatorTreeBuilder.EXPR_SLE,
    TranslatorTreeBuilder.EXPR_SEQ,
    TranslatorTreeBuilder.EXPR_SNE: begin
        reg2 := stack.getRegAt(1);
        reg3 := stack.getRegAt(0);
        sr2 := g.registerToString(reg2);
        sr3 := g.registerToString(reg3);
        stack.popRegs(2);
        case (node.getChild(0) as SyntaxNode).dataType.kind of
        TranslatorType.KIND_STRUCT, TranslatorType.KIND_ARRAY, TranslatorType.KIND_FUNC,
        TranslatorType.KIND_BOOLEAN, TranslatorType.KIND_INT: begin
            g.writeInstruction('cmp', sr2, sr3);
            if (goIfTrueTo <> nil) and (goIfFalseTo <> nil) then begin
                stack.restoreRegs(g); { регистр флагов – без изменений }
                if goIfTrueTo.labelNumber = nodeLN + 1 then begin
                    slbl := LABEL_LOCAL + intToString(goIfFalseTo.assignedLabelNumber);
                    case nodeValue of
                    TranslatorTreeBuilder.EXPR_SGT:
                        g.writeInstruction('jle', slbl);
                    TranslatorTreeBuilder.EXPR_SGE:
                        g.writeInstruction('jl', slbl);
                    TranslatorTreeBuilder.EXPR_SLT:
                        g.writeInstruction('jge', slbl);
                    TranslatorTreeBuilder.EXPR_SLE:
                        g.writeInstruction('jg', slbl);
                    TranslatorTreeBuilder.EXPR_SEQ:
                        g.writeInstruction('jne', slbl);
                    TranslatorTreeBuilder.EXPR_SNE:
                        g.writeInstruction('je', slbl);
                    end;
                end else
                if goIfFalseTo.labelNumber = nodeLN + 1 then begin
                    slbl := LABEL_LOCAL + intToString(goIfTrueTo.assignedLabelNumber);
                    case nodeValue of
                    TranslatorTreeBuilder.EXPR_SGT:
                        g.writeInstruction('jg', slbl);
                    TranslatorTreeBuilder.EXPR_SGE:
                        g.writeInstruction('jge', slbl);
                    TranslatorTreeBuilder.EXPR_SLT:
                        g.writeInstruction('jl', slbl);
                    TranslatorTreeBuilder.EXPR_SLE:
                        g.writeInstruction('jle', slbl);
                    TranslatorTreeBuilder.EXPR_SEQ:
                        g.writeInstruction('je', slbl);
                    TranslatorTreeBuilder.EXPR_SNE:
                        g.writeInstruction('jne', slbl);
                    end;
                end else begin
                    slbl := LABEL_LOCAL + intToString(goIfFalseTo.assignedLabelNumber);
                    case nodeValue of
                    TranslatorTreeBuilder.EXPR_SGT:
                        g.writeInstruction('jle', slbl);
                    TranslatorTreeBuilder.EXPR_SGE:
                        g.writeInstruction('jl', slbl);
                    TranslatorTreeBuilder.EXPR_SLT:
                        g.writeInstruction('jge', slbl);
                    TranslatorTreeBuilder.EXPR_SLE:
                        g.writeInstruction('jg', slbl);
                    TranslatorTreeBuilder.EXPR_SEQ:
                        g.writeInstruction('jne', slbl);
                    TranslatorTreeBuilder.EXPR_SNE:
                        g.writeInstruction('je', slbl);
                    end;
                    g.writeInstruction('jmp',
                            LABEL_LOCAL + intToString(goIfTrueTo.assignedLabelNumber));
                end;
            end else begin
                reg1 := stack.allocateGPR32bit(g); { регистр флагов – без изменений }
                srb := g.registerToString(AL + (reg1 and $0f));
                sr1 := g.registerToString(reg1);
                case nodeValue of
                TranslatorTreeBuilder.EXPR_SGT:
                    g.writeInstruction('setg', srb);
                TranslatorTreeBuilder.EXPR_SGE:
                    g.writeInstruction('setge', srb);
                TranslatorTreeBuilder.EXPR_SLT:
                    g.writeInstruction('setl', srb);
                TranslatorTreeBuilder.EXPR_SLE:
                    g.writeInstruction('setle', srb);
                TranslatorTreeBuilder.EXPR_SEQ:
                    g.writeInstruction('sete', srb);
                TranslatorTreeBuilder.EXPR_SNE:
                    g.writeInstruction('setne', srb);
                end;
                g.writeInstruction('movzx', sr1, srb);
                stack.restoreRegs(g);
            end;
        end;
        TranslatorType.KIND_FLOAT: begin
            case nodeValue of
            TranslatorTreeBuilder.EXPR_SGT: begin
                g.writeInstruction('cmpss', sr3, sr2, g.immediateToStringByte(1));
                g.writeInstruction('pmovmskb', sEDX, sr3);
            end;
            TranslatorTreeBuilder.EXPR_SGE: begin
                g.writeInstruction('cmpss', sr3, sr2, g.immediateToStringByte(2));
                g.writeInstruction('pmovmskb', sEDX, sr3);
            end;
            TranslatorTreeBuilder.EXPR_SLT: begin
                g.writeInstruction('cmpss', sr2, sr3, g.immediateToStringByte(1));
                g.writeInstruction('pmovmskb', sEDX, sr2);
            end;
            TranslatorTreeBuilder.EXPR_SLE: begin
                g.writeInstruction('cmpss', sr2, sr3, g.immediateToStringByte(2));
                g.writeInstruction('pmovmskb', sEDX, sr2);
            end;
            TranslatorTreeBuilder.EXPR_SEQ: begin
                g.writeInstruction('cmpss', sr2, sr3, g.immediateToStringByte(0));
                g.writeInstruction('pmovmskb', sEDX, sr2);
            end;
            TranslatorTreeBuilder.EXPR_SNE: begin
                g.writeInstruction('cmpss', sr2, sr3, g.immediateToStringByte(4));
                g.writeInstruction('pmovmskb', sEDX, sr2);
            end;
            end;
            g.writeInstruction('test', sEDX, g.immediateToStringShort($08));
            if (goIfTrueTo <> nil) and (goIfFalseTo <> nil) then begin
                stack.restoreRegs(g); { регистр флагов – без изменений }
                if goIfTrueTo.labelNumber = nodeLN + 1 then begin
                    g.writeInstruction('jz',
                            LABEL_LOCAL + intToString(goIfFalseTo.assignedLabelNumber));
                end else
                if goIfFalseTo.labelNumber = nodeLN + 1 then begin
                    g.writeInstruction('jnz',
                            LABEL_LOCAL + intToString(goIfTrueTo.assignedLabelNumber));
                end else begin
                    g.writeInstruction('jz',
                            LABEL_LOCAL + intToString(goIfFalseTo.assignedLabelNumber));
                    g.writeInstruction('jmp',
                            LABEL_LOCAL + intToString(goIfTrueTo.assignedLabelNumber));
                end;
            end else begin
                reg1 := stack.allocateGPR32bit(g); { регистр флагов – без изменений }
                srb := g.registerToString(AL + (reg1 and $0f));
                sr1 := g.registerToString(reg1);
                g.writeInstruction('setnz', srb);
                g.writeInstruction('movzx', sr1, srb);
                stack.restoreRegs(g);
            end;
        end;
        TranslatorType.KIND_DOUBLE: begin
            case nodeValue of
            TranslatorTreeBuilder.EXPR_SGT: begin
                g.writeInstruction('cmpsd', sr3, sr2, g.immediateToStringByte(1));
                g.writeInstruction('pmovmskb', sEDX, sr3);
            end;
            TranslatorTreeBuilder.EXPR_SGE: begin
                g.writeInstruction('cmpsd', sr3, sr2, g.immediateToStringByte(2));
                g.writeInstruction('pmovmskb', sEDX, sr3);
            end;
            TranslatorTreeBuilder.EXPR_SLT: begin
                g.writeInstruction('cmpsd', sr2, sr3, g.immediateToStringByte(1));
                g.writeInstruction('pmovmskb', sEDX, sr2);
            end;
            TranslatorTreeBuilder.EXPR_SLE: begin
                g.writeInstruction('cmpsd', sr2, sr3, g.immediateToStringByte(2));
                g.writeInstruction('pmovmskb', sEDX, sr2);
            end;
            TranslatorTreeBuilder.EXPR_SEQ: begin
                g.writeInstruction('cmpsd', sr2, sr3, g.immediateToStringByte(0));
                g.writeInstruction('pmovmskb', sEDX, sr2);
            end;
            TranslatorTreeBuilder.EXPR_SNE: begin
                g.writeInstruction('cmpsd', sr2, sr3, g.immediateToStringByte(4));
                g.writeInstruction('pmovmskb', sEDX, sr2);
            end;
            end;
            g.writeInstruction('test', sEDX, g.immediateToStringShort($80));
            if (goIfTrueTo <> nil) and (goIfFalseTo <> nil) then begin
                stack.restoreRegs(g); { регистр флагов – без изменений }
                if goIfTrueTo.labelNumber = nodeLN + 1 then begin
                    g.writeInstruction('jz',
                            LABEL_LOCAL + intToString(goIfFalseTo.assignedLabelNumber));
                end else
                if goIfFalseTo.labelNumber = nodeLN + 1 then begin
                    g.writeInstruction('jnz',
                            LABEL_LOCAL + intToString(goIfTrueTo.assignedLabelNumber));
                end else begin
                    g.writeInstruction('jz',
                            LABEL_LOCAL + intToString(goIfFalseTo.assignedLabelNumber));
                    g.writeInstruction('jmp',
                            LABEL_LOCAL + intToString(goIfTrueTo.assignedLabelNumber));
                end;
            end else begin
                reg1 := stack.allocateGPR32bit(g); { регистр флагов – без изменений }
                srb := g.registerToString(AL + (reg1 and $0f));
                sr1 := g.registerToString(reg1);
                g.writeInstruction('setnz', srb);
                g.writeInstruction('movzx', sr1, srb);
                stack.restoreRegs(g);
            end;
        end;
        TranslatorType.KIND_REAL: begin
            g.writeInstruction('fxch');
            g.writeInstruction('fcomip', sST0, sST1);
            g.writeInstruction('ffree', sST0);
            g.writeInstruction('fincstp');
            g.writeInstruction('jnp', LABEL_FOLLOWING);
            g.writeInstruction('mov', sDL, g.immediateToStringByte($ff));
            g.writeInstruction('or', sEDX, sEDX);
            if (nodeValue <> TranslatorTreeBuilder.EXPR_SLT) and
                    (nodeValue <> TranslatorTreeBuilder.EXPR_SLE) then begin
                g.writeInstruction('stc');
            end;
            g.writeLabelShort(LABEL_ANONYMOUS);
            if (goIfTrueTo <> nil) and (goIfFalseTo <> nil) then begin
                stack.restoreRegs(g); { регистр флагов – без изменений }
                if goIfTrueTo.labelNumber = nodeLN + 1 then begin
                    slbl := LABEL_LOCAL + intToString(goIfFalseTo.assignedLabelNumber);
                    case nodeValue of
                    TranslatorTreeBuilder.EXPR_SGT:
                        g.writeInstruction('jbe', slbl);
                    TranslatorTreeBuilder.EXPR_SGE:
                        g.writeInstruction('jb', slbl);
                    TranslatorTreeBuilder.EXPR_SLT:
                        g.writeInstruction('jae', slbl);
                    TranslatorTreeBuilder.EXPR_SLE:
                        g.writeInstruction('ja', slbl);
                    TranslatorTreeBuilder.EXPR_SEQ:
                        g.writeInstruction('jne', slbl);
                    TranslatorTreeBuilder.EXPR_SNE:
                        g.writeInstruction('je', slbl);
                    end;
                end else
                if goIfFalseTo.labelNumber = nodeLN + 1 then begin
                    slbl := LABEL_LOCAL + intToString(goIfTrueTo.assignedLabelNumber);
                    case nodeValue of
                    TranslatorTreeBuilder.EXPR_SGT:
                        g.writeInstruction('ja', slbl);
                    TranslatorTreeBuilder.EXPR_SGE:
                        g.writeInstruction('jae', slbl);
                    TranslatorTreeBuilder.EXPR_SLT:
                        g.writeInstruction('jb', slbl);
                    TranslatorTreeBuilder.EXPR_SLE:
                        g.writeInstruction('jbe', slbl);
                    TranslatorTreeBuilder.EXPR_SEQ:
                        g.writeInstruction('je', slbl);
                    TranslatorTreeBuilder.EXPR_SNE:
                        g.writeInstruction('jne', slbl);
                    end;
                end else begin
                    slbl := LABEL_LOCAL + intToString(goIfFalseTo.assignedLabelNumber);
                    case nodeValue of
                    TranslatorTreeBuilder.EXPR_SGT:
                        g.writeInstruction('jbe', slbl);
                    TranslatorTreeBuilder.EXPR_SGE:
                        g.writeInstruction('jb', slbl);
                    TranslatorTreeBuilder.EXPR_SLT:
                        g.writeInstruction('jae', slbl);
                    TranslatorTreeBuilder.EXPR_SLE:
                        g.writeInstruction('ja', slbl);
                    TranslatorTreeBuilder.EXPR_SEQ:
                        g.writeInstruction('jne', slbl);
                    TranslatorTreeBuilder.EXPR_SNE:
                        g.writeInstruction('je', slbl);
                    end;
                    g.writeInstruction('jmp',
                            LABEL_LOCAL + intToString(goIfTrueTo.assignedLabelNumber));
                end;
            end else begin
                reg1 := stack.allocateGPR32bit(g); { регистр флагов – без изменений }
                srb := g.registerToString(AL + (reg1 and $0f));
                sr1 := g.registerToString(reg1);
                case nodeValue of
                TranslatorTreeBuilder.EXPR_SGT:
                    g.writeInstruction('seta', srb);
                TranslatorTreeBuilder.EXPR_SGE:
                    g.writeInstruction('setae', srb);
                TranslatorTreeBuilder.EXPR_SLT:
                    g.writeInstruction('setb', srb);
                TranslatorTreeBuilder.EXPR_SLE:
                    g.writeInstruction('setbe', srb);
                TranslatorTreeBuilder.EXPR_SEQ:
                    g.writeInstruction('sete', srb);
                TranslatorTreeBuilder.EXPR_SNE:
                    g.writeInstruction('setne', srb);
                end;
                g.writeInstruction('movzx', sr1, srb);
                stack.restoreRegs(g);
            end;
        end;
        end;
    end;
    TranslatorTreeBuilder.EXPR_SANDB,
    TranslatorTreeBuilder.EXPR_SXORB,
    TranslatorTreeBuilder.EXPR_SORB: begin
        reg2 := stack.getRegAt(1);
        reg3 := stack.getRegAt(0);
        sr2 := g.registerToString(reg2);
        sr3 := g.registerToString(reg3);
        stack.popRegs(2);
        if (goIfTrueTo <> nil) and (goIfFalseTo <> nil) then begin
            case nodeValue of
            TranslatorTreeBuilder.EXPR_SANDB:
                g.writeInstruction('test', sr2, sr3);
            TranslatorTreeBuilder.EXPR_SXORB:
                g.writeInstruction('xor', sr2, sr3);
            TranslatorTreeBuilder.EXPR_SORB:
                g.writeInstruction('or', sr2, sr3);
            end;
            stack.restoreRegs(g); { регистр флагов – без изменений }
            if goIfTrueTo.labelNumber = nodeLN + 1 then begin
                g.writeInstruction('jz',
                        LABEL_LOCAL + intToString(goIfFalseTo.assignedLabelNumber));
            end else
            if goIfFalseTo.labelNumber = nodeLN + 1 then begin
                g.writeInstruction('jnz',
                        LABEL_LOCAL + intToString(goIfTrueTo.assignedLabelNumber));
            end else begin
                g.writeInstruction('jz',
                        LABEL_LOCAL + intToString(goIfFalseTo.assignedLabelNumber));
                g.writeInstruction('jmp',
                        LABEL_LOCAL + intToString(goIfTrueTo.assignedLabelNumber));
            end;
        end else begin
            if needAllocateForIndex(parentValue, nodeIndex) then begin
                reg1 := stack.allocateGPRForIndex(g);
            end else begin
                reg1 := stack.allocateGPR32bit(g);
            end;
            sr1 := g.registerToString(reg1);
            if reg1 <> reg2 then begin
                g.writeInstruction('mov', sr1, sr2);
            end;
            case nodeValue of
            TranslatorTreeBuilder.EXPR_SANDB:
                g.writeInstruction('and', sr1, sr3);
            TranslatorTreeBuilder.EXPR_SXORB:
                g.writeInstruction('xor', sr1, sr3);
            TranslatorTreeBuilder.EXPR_SORB:
                g.writeInstruction('or', sr1, sr3);
            end;
            stack.restoreRegs(g);
        end;
    end;
    TranslatorTreeBuilder.EXPR_SZR_TEST: begin
        reg2 := stack.getRegAt(1);
        reg3 := stack.getRegAt(0);
        sr2 := g.registerToString(reg2);
        sr3 := g.registerToString(reg3);
        stack.popRegs(2);
        g.writeInstruction('test', sr2, sr3);
        if (goIfTrueTo <> nil) and (goIfFalseTo <> nil) then begin
            stack.restoreRegs(g); { регистр флагов – без изменений }
            if goIfTrueTo.labelNumber = nodeLN + 1 then begin
                g.writeInstruction('jnz',
                        LABEL_LOCAL + intToString(goIfFalseTo.assignedLabelNumber));
            end else
            if goIfFalseTo.labelNumber = nodeLN + 1 then begin
                g.writeInstruction('jz',
                        LABEL_LOCAL + intToString(goIfTrueTo.assignedLabelNumber));
            end else begin
                g.writeInstruction('jnz',
                        LABEL_LOCAL + intToString(goIfFalseTo.assignedLabelNumber));
                g.writeInstruction('jmp',
                        LABEL_LOCAL + intToString(goIfTrueTo.assignedLabelNumber));
            end;
        end else begin
            reg1 := stack.allocateGPR32bit(g); { регистр флагов – без изменений }
            srb := g.registerToString(AL + (reg1 and $0f));
            sr1 := g.registerToString(reg1);
            g.writeInstruction('setz', srb);
            g.writeInstruction('movzx', sr1, srb);
            stack.restoreRegs(g);
        end;
    end;
    TranslatorTreeBuilder.EXPR_SNZ_TEST: begin
        reg2 := stack.getRegAt(1);
        reg3 := stack.getRegAt(0);
        sr2 := g.registerToString(reg2);
        sr3 := g.registerToString(reg3);
        stack.popRegs(2);
        g.writeInstruction('test', sr2, sr3);
        if (goIfTrueTo <> nil) and (goIfFalseTo <> nil) then begin
            stack.restoreRegs(g); { регистр флагов – без изменений }
            if goIfTrueTo.labelNumber = nodeLN + 1 then begin
                g.writeInstruction('jz',
                        LABEL_LOCAL + intToString(goIfFalseTo.assignedLabelNumber));
            end else
            if goIfFalseTo.labelNumber = nodeLN + 1 then begin
                g.writeInstruction('jnz',
                        LABEL_LOCAL + intToString(goIfTrueTo.assignedLabelNumber));
            end else begin
                g.writeInstruction('jz',
                        LABEL_LOCAL + intToString(goIfFalseTo.assignedLabelNumber));
                g.writeInstruction('jmp',
                        LABEL_LOCAL + intToString(goIfTrueTo.assignedLabelNumber));
            end;
        end else begin
            reg1 := stack.allocateGPR32bit(g); { регистр флагов – без изменений }
            srb := g.registerToString(AL + (reg1 and $0f));
            sr1 := g.registerToString(reg1);
            g.writeInstruction('setnz', srb);
            g.writeInstruction('movzx', sr1, srb);
            stack.restoreRegs(g);
        end;
    end;
    TranslatorTreeBuilder.EXPR_SEQ_NULL: begin
        reg2 := stack.getRegAt(0);
        sr2 := g.registerToString(reg2);
        stack.popRegs(1);
        g.writeInstruction('test', sr2, sr2);
        if (goIfTrueTo <> nil) and (goIfFalseTo <> nil) then begin
            stack.restoreRegs(g); { регистр флагов – без изменений }
            if goIfTrueTo.labelNumber = nodeLN + 1 then begin
                g.writeInstruction('jnz',
                        LABEL_LOCAL + intToString(goIfFalseTo.assignedLabelNumber));
            end else
            if goIfFalseTo.labelNumber = nodeLN + 1 then begin
                g.writeInstruction('jz',
                        LABEL_LOCAL + intToString(goIfTrueTo.assignedLabelNumber));
            end else begin
                g.writeInstruction('jnz',
                        LABEL_LOCAL + intToString(goIfFalseTo.assignedLabelNumber));
                g.writeInstruction('jmp',
                        LABEL_LOCAL + intToString(goIfTrueTo.assignedLabelNumber));
            end;
        end else begin
            reg1 := stack.allocateGPR32bit(g); { регистр флагов – без изменений }
            srb := g.registerToString(AL + (reg1 and $0f));
            sr1 := g.registerToString(reg1);
            g.writeInstruction('setz', srb);
            g.writeInstruction('movzx', sr1, srb);
            stack.restoreRegs(g);
        end;
    end;
    TranslatorTreeBuilder.EXPR_SNE_NULL: begin
        reg2 := stack.getRegAt(0);
        sr2 := g.registerToString(reg2);
        stack.popRegs(1);
        g.writeInstruction('test', sr2, sr2);
        if (goIfTrueTo <> nil) and (goIfFalseTo <> nil) then begin
            stack.restoreRegs(g); { регистр флагов – без изменений }
            if goIfTrueTo.labelNumber = nodeLN + 1 then begin
                g.writeInstruction('jz',
                        LABEL_LOCAL + intToString(goIfFalseTo.assignedLabelNumber));
            end else
            if goIfFalseTo.labelNumber = nodeLN + 1 then begin
                g.writeInstruction('jnz',
                        LABEL_LOCAL + intToString(goIfTrueTo.assignedLabelNumber));
            end else begin
                g.writeInstruction('jz',
                        LABEL_LOCAL + intToString(goIfFalseTo.assignedLabelNumber));
                g.writeInstruction('jmp',
                        LABEL_LOCAL + intToString(goIfTrueTo.assignedLabelNumber));
            end;
        end else begin
            reg1 := stack.allocateGPR32bit(g); { регистр флагов – без изменений }
            srb := g.registerToString(AL + (reg1 and $0f));
            sr1 := g.registerToString(reg1);
            g.writeInstruction('setnz', srb);
            g.writeInstruction('movzx', sr1, srb);
            stack.restoreRegs(g);
        end;
    end;
    TranslatorTreeBuilder.ASSIGN: begin
        child := node.getChild(0) as SyntaxNode;
        mem := getMemoryLocation(child, stack, true);
        smm := mem.memoryToString(MNONE, 0);
        smmt := mem.memoryToString(MREAL, 0);
        reg2 := mem.getRegisterSource();
        srb := g.registerToString(AL + (reg2 and $0f));
        srw := g.registerToString(AX + (reg2 and $0f));
        sr2 := g.registerToString(reg2);
        buffer := child.dataType.kind;
        case buffer of
        TranslatorType.KIND_BOOLEAN: begin
            g.writeInstruction('mov', smm, srb);
            if (goIfTrueTo <> nil) and (goIfFalseTo <> nil) then begin
                g.writeInstruction('test', sr2, sr2);
                stack.restoreRegs(g); { регистр флагов – без изменений }
                if goIfTrueTo.labelNumber = nodeLN + 1 then begin
                    g.writeInstruction('jz',
                            LABEL_LOCAL + intToString(goIfFalseTo.assignedLabelNumber));
                end else
                if goIfFalseTo.labelNumber = nodeLN + 1 then begin
                    g.writeInstruction('jnz',
                            LABEL_LOCAL + intToString(goIfTrueTo.assignedLabelNumber));
                end else begin
                    g.writeInstruction('jz',
                            LABEL_LOCAL + intToString(goIfFalseTo.assignedLabelNumber));
                    g.writeInstruction('jmp',
                            LABEL_LOCAL + intToString(goIfTrueTo.assignedLabelNumber));
                end;
            end else begin
                if nodeType <> nil then begin
                    reg1 := stack.allocateGPR32bit(g);
                    if reg1 <> reg2 then begin
                        sr1 := g.registerToString(reg1);
                        g.writeInstruction('mov', sr1, sr2);
                    end;
                end;
                stack.restoreRegs(g);
            end;
        end;
        TranslatorType.KIND_CHAR, TranslatorType.KIND_BYTE,
        TranslatorType.KIND_SHORT, TranslatorType.KIND_INT: begin
            case buffer of
            TranslatorType.KIND_CHAR, TranslatorType.KIND_SHORT:
                g.writeInstruction('mov', smm, srw);
            TranslatorType.KIND_BYTE:
                g.writeInstruction('mov', smm, srb);
            TranslatorType.KIND_INT:
                g.writeInstruction('mov', smm, sr2);
            end;
            if nodeType <> nil then begin
                if needAllocateForIndex(parentValue, nodeIndex) then begin
                    reg1 := stack.allocateGPRForIndex(g);
                end else begin
                    reg1 := stack.allocateGPR32bit(g);
                end;
                if reg1 <> reg2 then begin
                    sr1 := g.registerToString(reg1);
                    g.writeInstruction('mov', sr1, sr2);
                end;
            end;
            stack.restoreRegs(g);
        end;
        TranslatorType.KIND_FLOAT: begin
            g.writeInstruction('movss', smm, sr2);
            if nodeType <> nil then begin
                stack.pushReg(reg2);
            end;
            stack.restoreRegs(g);
        end;
        TranslatorType.KIND_DOUBLE: begin
            g.writeInstruction('movsd', smm, sr2);
            if nodeType <> nil then begin
                stack.pushReg(reg2);
            end;
            stack.restoreRegs(g);
        end;
        TranslatorType.KIND_REAL: begin
            g.writeInstruction('fstp', smmt);
            if nodeType <> nil then begin
                stack.pushReg(ST);
                g.writeInstruction('fld', smmt);
            end;
            stack.restoreRegs(g);
        end;
        TranslatorType.KIND_STRUCT, TranslatorType.KIND_ARRAY, TranslatorType.KIND_FUNC: begin
            g.writeInstruction('mov', smm, sr2);
            if nodeType <> nil then begin
                if needAllocateForPointer(parentValue, nodeIndex) then begin
                    reg1 := stack.allocateGPRForPointer(g);
                end else
                if needAllocateForArray(parentValue, nodeIndex) then begin
                    reg1 := stack.allocateGPRForArray(g);
                end else begin
                    reg1 := stack.allocateGPR32bit(g);
                end;
                if reg1 <> reg2 then begin
                    sr1 := g.registerToString(reg1);
                    g.writeInstruction('mov', sr1, sr2);
                end;
            end;
            stack.restoreRegs(g);
        end;
        end;
    end;
    TranslatorTreeBuilder.ASSIGN_SADD,
    TranslatorTreeBuilder.ASSIGN_SSUB,
    TranslatorTreeBuilder.ASSIGN_SMULL: begin
        child := node.getChild(0) as SyntaxNode;
        mem := getMemoryLocation(child, stack, true);
        smm := mem.memoryToString(MNONE, 0);
        smmb := mem.memoryToString(MBYTE, 0);
        smmw := mem.memoryToString(MWORD, 0);
        smmt := mem.memoryToString(MREAL, 0);
        reg2 := mem.getRegisterSource();
        sr2 := g.registerToString(reg2);
        buffer := child.dataType.kind;
        case buffer of
        TranslatorType.KIND_CHAR, TranslatorType.KIND_BYTE,
        TranslatorType.KIND_SHORT, TranslatorType.KIND_INT: begin
            case buffer of
            TranslatorType.KIND_CHAR:
                g.writeInstruction('movzx', sEDX, smmw);
            TranslatorType.KIND_BYTE:
                g.writeInstruction('movsx', sEDX, smmb);
            TranslatorType.KIND_SHORT:
                g.writeInstruction('movsx', sEDX, smmw);
            TranslatorType.KIND_INT:
                g.writeInstruction('mov', sEDX, smm);
            end;
            case nodeValue of
            TranslatorTreeBuilder.ASSIGN_SADD:
                g.writeInstruction('add', sEDX, sr2);
            TranslatorTreeBuilder.ASSIGN_SSUB:
                g.writeInstruction('sub', sEDX, sr2);
            TranslatorTreeBuilder.ASSIGN_SMULL:
                g.writeInstruction('imul', sEDX, sr2);
            end;
            case buffer of
            TranslatorType.KIND_BYTE:
                g.writeInstruction('mov', smm, sDL);
            TranslatorType.KIND_SHORT, TranslatorType.KIND_CHAR:
                g.writeInstruction('mov', smm, sDX);
            TranslatorType.KIND_INT:
                g.writeInstruction('mov', smm, sEDX);
            end;
            if nodeType <> nil then begin
                if needAllocateForIndex(parentValue, nodeIndex) then begin
                    reg1 := stack.allocateGPRForIndex(g);
                end else begin
                    reg1 := stack.allocateGPR32bit(g);
                end;
                sr1 := g.registerToString(reg1);
                g.writeInstruction('mov', sr1, sEDX);
            end;
        end;
        TranslatorType.KIND_FLOAT: begin
            g.writeInstruction('movss', sXMM4, smm);
            case nodeValue of
            TranslatorTreeBuilder.ASSIGN_SADD:
                g.writeInstruction('addss', sXMM4, sr2);
            TranslatorTreeBuilder.ASSIGN_SSUB:
                g.writeInstruction('subss', sXMM4, sr2);
            TranslatorTreeBuilder.ASSIGN_SMULL:
                g.writeInstruction('mulss', sXMM4, sr2);
            end;
            g.writeInstruction('movss', smm, sXMM4);
            if nodeType <> nil then begin
                stack.pushReg(reg2);
                g.writeInstruction('movss', sr2, sXMM4);
            end;
        end;
        TranslatorType.KIND_DOUBLE: begin
            g.writeInstruction('movsd', sXMM4, smm);
            case nodeValue of
            TranslatorTreeBuilder.ASSIGN_SADD:
                g.writeInstruction('addsd', sXMM4, sr2);
            TranslatorTreeBuilder.ASSIGN_SSUB:
                g.writeInstruction('subsd', sXMM4, sr2);
            TranslatorTreeBuilder.ASSIGN_SMULL:
                g.writeInstruction('mulsd', sXMM4, sr2);
            end;
            g.writeInstruction('movsd', smm, sXMM4);
            if nodeType <> nil then begin
                stack.pushReg(reg2);
                g.writeInstruction('movsd', sr2, sXMM4);
            end;
        end;
        TranslatorType.KIND_REAL: begin
            stack.pushReg(ST);
            stack.allocateFPU(1, g);
            g.writeInstruction('fld', smmt);
            case nodeValue of
            TranslatorTreeBuilder.ASSIGN_SADD:
                g.writeInstruction('fadd', sST0, sST1);
            TranslatorTreeBuilder.ASSIGN_SSUB:
                g.writeInstruction('fsub', sST0, sST1);
            TranslatorTreeBuilder.ASSIGN_SMULL:
                g.writeInstruction('fmul', sST0, sST1);
            end;
            g.writeInstruction('fstp', sST1);
            g.writeInstruction('fstp', smmt);
            if nodeType <> nil then begin
                g.writeInstruction('fld', smmt);
                stack.popRegs(1);
            end else begin
                stack.popRegs(2);
            end;
        end;
        end;
        stack.restoreRegs(g);
    end;
    TranslatorTreeBuilder.ASSIGN_SDIVS,
    TranslatorTreeBuilder.ASSIGN_SDIVU: begin
        child := node.getChild(0) as SyntaxNode;
        mem := getMemoryLocation(child, stack, true);
        smm := mem.memoryToString(MNONE, 0);
        smmb := mem.memoryToString(MBYTE, 0);
        smmw := mem.memoryToString(MWORD, 0);
        smmt := mem.memoryToString(MREAL, 0);
        reg2 := mem.getRegisterSource();
        sr2 := g.registerToString(reg2);
        buffer := child.dataType.kind;
        case buffer of
        TranslatorType.KIND_CHAR, TranslatorType.KIND_BYTE,
        TranslatorType.KIND_SHORT, TranslatorType.KIND_INT: begin
            regInUse := stack.isUsedRegister(EAX);
            if regInUse then begin
                g.writeInstruction('mov', sEDI, sEAX);
            end else
            if reg2 = EAX then begin
                g.writeInstruction('mov', sEDI, sEAX);
                reg2 := EDI;
                sr2 := sEDI;
            end;
            case buffer of
            TranslatorType.KIND_CHAR:
                g.writeInstruction('movzx', sEAX, smmw);
            TranslatorType.KIND_BYTE:
                g.writeInstruction('movsx', sEAX, smmb);
            TranslatorType.KIND_SHORT:
                g.writeInstruction('movsx', sEAX, smmw);
            TranslatorType.KIND_INT:
                g.writeInstruction('mov', sEAX, smm);
            end;
            case nodeValue of
            TranslatorTreeBuilder.ASSIGN_SDIVS: begin
                g.writeInstruction('cdq');
                g.writeInstruction('idiv', sr2);
            end;
            TranslatorTreeBuilder.ASSIGN_SDIVU: begin
                g.writeInstruction('xor', sEDX, sEDX);
                g.writeInstruction('div', sr2);
            end;
            end;
            case buffer of
            TranslatorType.KIND_BYTE:
                g.writeInstruction('mov', smm, sAL);
            TranslatorType.KIND_SHORT, TranslatorType.KIND_CHAR:
                g.writeInstruction('mov', smm, sAX);
            TranslatorType.KIND_INT:
                g.writeInstruction('mov', smm, sEAX);
            end;
            if nodeType <> nil then begin
                if needAllocateForIndex(parentValue, nodeIndex) then begin
                    reg1 := stack.allocateGPRForIndex(g);
                end else begin
                    reg1 := stack.allocateGPR32bit(g);
                end;
                if reg1 <> EAX then begin
                    sr1 := g.registerToString(reg1);
                    g.writeInstruction('mov', sr1, sEAX);
                end;
            end;
            if regInUse then begin
                g.writeInstruction('mov', sEAX, sEDI);
            end;
        end;
        TranslatorType.KIND_FLOAT: begin
            g.writeInstruction('movss', sXMM4, smm);
            g.writeInstruction('divss', sXMM4, sr2);
            g.writeInstruction('movss', smm, sXMM4);
            if nodeType <> nil then begin
                stack.pushReg(reg2);
                g.writeInstruction('movss', sr2, sXMM4);
            end;
        end;
        TranslatorType.KIND_DOUBLE: begin
            g.writeInstruction('movsd', sXMM4, smm);
            g.writeInstruction('divsd', sXMM4, sr2);
            g.writeInstruction('movsd', smm, sXMM4);
            if nodeType <> nil then begin
                stack.pushReg(reg2);
                g.writeInstruction('movsd', sr2, sXMM4);
            end;
        end;
        TranslatorType.KIND_REAL: begin
            stack.pushReg(ST);
            stack.allocateFPU(1, g);
            g.writeInstruction('fld', smmt);
            g.writeInstruction('fdiv', sST0, sST1);
            g.writeInstruction('fstp', sST1);
            g.writeInstruction('fstp', smmt);
            if nodeType <> nil then begin
                g.writeInstruction('fld', smmt);
                stack.popRegs(1);
            end else begin
                stack.popRegs(2);
            end;
        end;
        end;
        stack.restoreRegs(g);
    end;
    TranslatorTreeBuilder.ASSIGN_SREMS,
    TranslatorTreeBuilder.ASSIGN_SREMU: begin
        child := node.getChild(0) as SyntaxNode;
        mem := getMemoryLocation(child, stack, true);
        smm := mem.memoryToString(MNONE, 0);
        smmb := mem.memoryToString(MBYTE, 0);
        smmw := mem.memoryToString(MWORD, 0);
        reg2 := mem.getRegisterSource();
        sr2 := g.registerToString(reg2);
        buffer := child.dataType.kind;
        case buffer of
        TranslatorType.KIND_CHAR, TranslatorType.KIND_BYTE,
        TranslatorType.KIND_SHORT, TranslatorType.KIND_INT: begin
            regInUse := stack.isUsedRegister(EAX);
            if regInUse then begin
                g.writeInstruction('mov', sEDI, sEAX);
            end else
            if reg2 = EAX then begin
                g.writeInstruction('mov', sEDI, sEAX);
                reg2 := EDI;
                sr2 := sEDI;
            end;
            case buffer of
            TranslatorType.KIND_CHAR:
                g.writeInstruction('movzx', sEAX, smmw);
            TranslatorType.KIND_BYTE:
                g.writeInstruction('movsx', sEAX, smmb);
            TranslatorType.KIND_SHORT:
                g.writeInstruction('movsx', sEAX, smmw);
            TranslatorType.KIND_INT:
                g.writeInstruction('mov', sEAX, smm);
            end;
            case nodeValue of
            TranslatorTreeBuilder.ASSIGN_SREMS: begin
                g.writeInstruction('cdq');
                g.writeInstruction('idiv', sr2);
            end;
            TranslatorTreeBuilder.ASSIGN_SREMU: begin
                g.writeInstruction('xor', sEDX, sEDX);
                g.writeInstruction('div', sr2);
            end;
            end;
            case buffer of
            TranslatorType.KIND_BYTE:
                g.writeInstruction('mov', smm, sDL);
            TranslatorType.KIND_SHORT, TranslatorType.KIND_CHAR:
                g.writeInstruction('mov', smm, sDX);
            TranslatorType.KIND_INT:
                g.writeInstruction('mov', smm, sEDX);
            end;
            if nodeType <> nil then begin
                if needAllocateForIndex(parentValue, nodeIndex) then begin
                    reg1 := stack.allocateGPRForIndex(g);
                end else begin
                    reg1 := stack.allocateGPR32bit(g);
                end;
                if reg1 <> EDX then begin
                    sr1 := g.registerToString(reg1);
                    g.writeInstruction('mov', sr1, sEDX);
                end;
            end;
            if regInUse then begin
                g.writeInstruction('mov', sEAX, sEDI);
            end;
        end;
        TranslatorType.KIND_FLOAT, TranslatorType.KIND_DOUBLE, TranslatorType.KIND_REAL: begin
            regInUse := stack.isUsedRegister(EAX);
            case buffer of
            TranslatorType.KIND_FLOAT:
                smmt := mem.memoryToString(MFLOAT, 0);
            TranslatorType.KIND_DOUBLE:
                smmt := mem.memoryToString(MDOUBLE, 0);
            TranslatorType.KIND_REAL:
                smmt := mem.memoryToString(MREAL, 0);
            else
                smmt := '';
            end;
            stack.pushReg(ST);
            stack.allocateFPU(1, g);
            if regInUse then begin
                g.writeInstruction('mov', sEDX, sEAX);
            end;
            g.writeInstruction('fld', smmt);
            g.writeLabelShort(LABEL_ANONYMOUS);
            g.writeInstruction('fprem');
            g.writeInstruction('fnstsw', sAX);
            g.writeInstruction('test', sEAX, g.immediateToStringShort($0400));
            g.writeInstruction('jnz', LABEL_PRECEDING);
            g.writeInstruction('fstp', sST1);
            g.writeInstruction('fstp', smmt);
            if nodeType <> nil then begin
                g.writeInstruction('fld', smmt);
                stack.popRegs(1);
            end else begin
                stack.popRegs(2);
            end;
            if regInUse then begin
                g.writeInstruction('mov', sEAX, sEDX);
            end;
        end;
        end;
        stack.restoreRegs(g);
    end;
    TranslatorTreeBuilder.ASSIGN_SSLL,
    TranslatorTreeBuilder.ASSIGN_SSRA,
    TranslatorTreeBuilder.ASSIGN_SSRL: begin
        child := node.getChild(1) as SyntaxNode;
        if child.value <> TranslatorTreeBuilder.EXPR_VALUE_INT then begin
            child := node.getChild(0) as SyntaxNode;
            mem := getMemoryLocation(child, stack, true);
            smm := mem.memoryToString(MNONE, 0);
            smmb := mem.memoryToString(MBYTE, 0);
            smmw := mem.memoryToString(MWORD, 0);
            reg2 := mem.getRegisterSource();
            sr2 := g.registerToString(reg2);
            buffer := child.dataType.kind;
            regInUse := stack.isUsedRegister(ECX);
            if regInUse then begin
                g.writeInstruction('mov', sEDI, sECX);
            end;
            if reg2 <> ECX then begin
                g.writeInstruction('mov', sECX, sr2);
            end;
            case buffer of
            TranslatorType.KIND_CHAR:
                g.writeInstruction('movzx', sEDX, smmw);
            TranslatorType.KIND_BYTE:
                g.writeInstruction('movsx', sEDX, smmb);
            TranslatorType.KIND_SHORT:
                g.writeInstruction('movsx', sEDX, smmw);
            TranslatorType.KIND_INT:
                g.writeInstruction('mov', sEDX, smm);
            end;
            case nodeValue of
            TranslatorTreeBuilder.ASSIGN_SSLL:
                g.writeInstruction('shl', sEDX, sCL);
            TranslatorTreeBuilder.ASSIGN_SSRA:
                g.writeInstruction('sar', sEDX, sCL);
            TranslatorTreeBuilder.ASSIGN_SSRL:
                g.writeInstruction('shr', sEDX, sCL);
            end;
        end else begin
            buffer := (child.associate as IntegerAsObject).byteValue();
            child := node.getChild(0) as SyntaxNode;
            mem := getMemoryLocation(child, stack, false);
            smm := mem.memoryToString(MNONE, 0);
            smmb := mem.memoryToString(MBYTE, 0);
            smmw := mem.memoryToString(MWORD, 0);
            simm := g.immediateToStringByte(buffer);
            buffer := child.dataType.kind;
            regInUse := false;
            case buffer of
            TranslatorType.KIND_CHAR:
                g.writeInstruction('movzx', sEDX, smmw);
            TranslatorType.KIND_BYTE:
                g.writeInstruction('movsx', sEDX, smmb);
            TranslatorType.KIND_SHORT:
                g.writeInstruction('movsx', sEDX, smmw);
            TranslatorType.KIND_INT:
                g.writeInstruction('mov', sEDX, smm);
            end;
            case nodeValue of
            TranslatorTreeBuilder.ASSIGN_SSLL:
                g.writeInstruction('shl', sEDX, simm);
            TranslatorTreeBuilder.ASSIGN_SSRA:
                g.writeInstruction('sar', sEDX, simm);
            TranslatorTreeBuilder.ASSIGN_SSRL:
                g.writeInstruction('shr', sEDX, simm);
            end;
        end;
        case buffer of
        TranslatorType.KIND_BYTE:
            g.writeInstruction('mov', smm, sDL);
        TranslatorType.KIND_SHORT, TranslatorType.KIND_CHAR:
            g.writeInstruction('mov', smm, sDX);
        TranslatorType.KIND_INT:
            g.writeInstruction('mov', smm, sEDX);
        end;
        if nodeType <> nil then begin
            if needAllocateForIndex(parentValue, nodeIndex) then begin
                reg1 := stack.allocateGPRForIndex(g);
            end else begin
                reg1 := stack.allocateGPR32bit(g);
            end;
            if reg1 <> EDX then begin
                sr1 := g.registerToString(reg1);
                g.writeInstruction('mov', sr1, sEDX);
            end;
        end;
        if regInUse then begin
            g.writeInstruction('mov', sECX, sEDI);
        end;
        stack.restoreRegs(g);
    end;
    TranslatorTreeBuilder.ASSIGN_SANDB,
    TranslatorTreeBuilder.ASSIGN_SXORB,
    TranslatorTreeBuilder.ASSIGN_SORB: begin
        child := node.getChild(0) as SyntaxNode;
        mem := getMemoryLocation(child, stack, true);
        smm := mem.memoryToString(MNONE, 0);
        smmb := mem.memoryToString(MBYTE, 0);
        smmw := mem.memoryToString(MWORD, 0);
        reg2 := mem.getRegisterSource();
        sr2 := g.registerToString(reg2);
        buffer := child.dataType.kind;
        case buffer of
        TranslatorType.KIND_BOOLEAN:
            g.writeInstruction('movzx', sEDX, smmb);
        TranslatorType.KIND_CHAR:
            g.writeInstruction('movzx', sEDX, smmw);
        TranslatorType.KIND_BYTE:
            g.writeInstruction('movsx', sEDX, smmb);
        TranslatorType.KIND_SHORT:
            g.writeInstruction('movsx', sEDX, smmw);
        TranslatorType.KIND_INT:
            g.writeInstruction('mov', sEDX, smm);
        end;
        case nodeValue of
        TranslatorTreeBuilder.ASSIGN_SANDB:
            g.writeInstruction('and', sEDX, sr2);
        TranslatorTreeBuilder.ASSIGN_SXORB:
            g.writeInstruction('xor', sEDX, sr2);
        TranslatorTreeBuilder.ASSIGN_SORB:
            g.writeInstruction('or', sEDX, sr2);
        end;
        case buffer of
        TranslatorType.KIND_BYTE, TranslatorType.KIND_BOOLEAN:
            g.writeInstruction('mov', smm, sDL);
        TranslatorType.KIND_SHORT, TranslatorType.KIND_CHAR:
            g.writeInstruction('mov', smm, sDX);
        TranslatorType.KIND_INT:
            g.writeInstruction('mov', smm, sEDX);
        end;
        if (goIfTrueTo <> nil) and (goIfFalseTo <> nil) then begin
            stack.restoreRegs(g); { регистр флагов – без изменений }
            if goIfTrueTo.labelNumber = nodeLN + 1 then begin
                g.writeInstruction('jz',
                        LABEL_LOCAL + intToString(goIfFalseTo.assignedLabelNumber));
            end else
            if goIfFalseTo.labelNumber = nodeLN + 1 then begin
                g.writeInstruction('jnz',
                        LABEL_LOCAL + intToString(goIfTrueTo.assignedLabelNumber));
            end else begin
                g.writeInstruction('jz',
                        LABEL_LOCAL + intToString(goIfFalseTo.assignedLabelNumber));
                g.writeInstruction('jmp',
                        LABEL_LOCAL + intToString(goIfTrueTo.assignedLabelNumber));
            end;
        end else begin
            if nodeType <> nil then begin
                if needAllocateForIndex(parentValue, nodeIndex) then begin
                    reg1 := stack.allocateGPRForIndex(g);
                end else begin
                    reg1 := stack.allocateGPR32bit(g);
                end;
                if reg1 <> EDX then begin
                    sr1 := g.registerToString(reg1);
                    g.writeInstruction('mov', sr1, sEDX);
                end;
            end;
            stack.restoreRegs(g);
        end;
    end;
    TranslatorTreeBuilder.JUMP: begin
        if (node.parent as SyntaxNode).value = TranslatorTreeBuilder.EXPR_QUESTION then begin
            stack.deallocateRegWithoutCodeGeneration();
        end;
        g.writeInstruction('jmp', LABEL_LOCAL + intToString(goAlwaysTo.assignedLabelNumber));
    end;
    end;
end;

procedure TranslatorBuilderOf32bitCode.translateSwitch(node: SyntaxNode; stack: RegisterStack);
var
    i: int;
    j: int;
    k: int;
    reg1: int;
    caseC: int;
    caseF: int;
    caseS: int;
    delta: int;
    count: int;
    default: int;
    current: long;
    labels: long_Array1d;
    child: BuilderNode;
    g: TextGenerator;
    slabels: String_Array1d;
    sdef: String;
    sr1: String;

    procedure addLabel(caseValue, nodeLabel: int); inline;
    var
        newlabels: long_Array1d;
    begin
        if length(labels) = count then begin
            newlabels := long_Array1d_create((count shl 1) + 1);
            arraycopyPrimitives(labels, 0, newlabels, 0, count);
            labels := newlabels;
        end;
        labels[count] := longBuild(nodeLabel, caseValue);
        inc(count);
    end;

    procedure sortLabels(); inline;
    var
        i: int;
        j: int;
        valueAtI: int;
        valueAtJ: int;
        labelAtI: long;
        labelAtJ: long;
    begin
        for i := count - 1 downto 1 do begin
            labelAtI := labels[i];
            valueAtI := int(labelAtI);
            j := i - 1;
            while j >= 0 do begin
                labelAtJ := labels[j];
                valueAtJ := int(labelAtJ);
                if valueAtJ > valueAtI then begin
                    labels[i] := labelAtJ;
                    labels[j] := labelAtI;
                    labelAtI := labelAtJ;
                    valueAtI := valueAtJ;
                    j := i;
                end;
                dec(j);
            end;
        end;
    end;

    procedure setLabelsLength(newLength: int); inline;
    var
        newlabels: String_Array1d;
    begin
        if newLength < length(slabels) then begin
            newlabels := String_Array1d_create(newLength);
            arraycopyStrings(slabels, 0, newlabels, 0, newLength);
            slabels := newlabels;
        end;
    end;

begin
    g := self.generator;
    count := 0;
    default := -1;
    labels := nil;
    reg1 := stack.getRegAt(0);
    sr1 := g.registerToString(reg1);
    stack.popRegs(1);
    for i := node.getChildrensCount() - 1 downto 0 do begin
        child := node.getChild(i) as BuilderNode;
        case child.value of
        TranslatorTreeBuilder.BLOCK_CASE:
            addLabel((child.associate as IntegerAsObject).intValue(),
                    (child.goAlwaysToNode as BuilderNode).assignedLabelNumber);
        TranslatorTreeBuilder.BLOCK_DEFAULT:
            default := (child.goAlwaysToNode as BuilderNode).assignedLabelNumber;
        end;
    end;
    sortLabels();
    sdef := LABEL_LOCAL + intToString(default);
    if count > 0 then begin
        caseS := int(labels[0]);
        caseF := int(labels[count - 1]);
    end else begin
        caseS := 0;
        caseF := -1;
    end;
    caseC := caseF - caseS + 1;
    if (caseC > 0) and (caseC < count shl 1) then begin
        { tableswitch }
        g.writeInstruction('sub', sr1, g.immediateToStringInt(caseS));
        g.writeInstruction('jl', sdef);
        g.writeInstruction('cmp', sr1, g.immediateToStringInt(caseF - caseS));
        g.writeInstruction('ja', sdef);
        g.writeInstruction('jmp', g.memoryToString(MDWORD, LABEL_FOLLOWING, reg1, 4, 0));
        g.writeAlignLocal(4);
        g.writeLabelShort(LABEL_ANONYMOUS);
        i := 0;
        k := 0;
        slabels := String_Array1d_create(8);
        for j := caseS to caseF do begin
            current := labels[i];
            if int(current) = j then begin
                slabels[k] := LABEL_LOCAL + intToString(current.ints[1]);
                inc(i);
            end else begin
                slabels[k] := sdef;
            end;
            inc(k);
            if k = 8 then begin
                g.writeInstruction('dd', slabels);
                k := 0;
            end;
        end;
        if k > 0 then begin
            setLabelsLength(k);
            g.writeInstruction('dd', slabels);
        end;
    end else begin
        { lookupswitch }
        dec(count);
        for i := 0 to count do begin
            current := labels[i];
            delta := int(current);
            if i > 0 then begin
                dec(delta, int(labels[i - 1]));
            end;
            g.writeInstruction('sub', sr1, g.immediateToStringInt(delta));
            g.writeInstruction('jz', LABEL_LOCAL + intToString(current.ints[1]));
        end;
        g.writeInstruction('jmp', sdef);
    end;
end;

procedure TranslatorBuilderOf32bitCode.writePools();
var
    i: int;
    j: int;
    k: int;
    l: int;
    len: int;
    limit: int;
    exponent: int;
    significand: long;
    floatValue: float;
    doubleValue: double;
    realValue: real;
    funcValue: GlobalFunction;
    poolOfReal: PoolReal;
    poolOfString: PoolString;
    poolOfFunctions: Vector;
    representer: RealValueRepresenter;
    g: TextGenerator;
    schars: String_Array1d;
    stringValue: UnicodeString;
    funcOwner: UnicodeString;
    shex: String;
    sdec: String;
begin
    g := self.generator;

    {%region открытые функции, имеющиеся в программе}
    poolOfFunctions := programmeFunctions;
    poolOfString := programmeStrings;
    limit := poolOfFunctions.size() - 1;
    g.writeEmptyLine();
    g.writeCommentToLineEnd('pool of functions');
    g.writeAlignGlobal(4);
    g.writeLabelLong(LABEL_POOL_FUNCS_LENGTH);
    g.writeInstruction('dd', g.immediateToStringInt(limit + 1));
    g.writeLabelLong(LABEL_POOL_FUNCS_CONTENT);
    for i := 0 to limit do begin
        funcValue := poolOfFunctions.elementAt(i) as GlobalFunction;
        stringValue := funcValue.name;
        funcOwner := funcValue.owner.name;
        if length(funcOwner) > 0 then begin
            stringValue := funcOwner + '.' + stringValue;
        end;
        g.writeInstruction('dd', g.immediateToStringInt(poolOfString.indexAcquire(stringValue)),
                getEntryFullName(funcValue));
    end;
    g.writeEmptyLine();
    {%endregion}

    {%region числа типа float, используемые программой }
    poolOfReal := programmeFloats;
    limit := poolOfReal.getLength() - 1;
    g.writeEmptyLine();
    g.writeCommentToLineEnd('pool of float');
    g.writeLabelLong(LABEL_POOL_FLOAT_LENGTH);
    g.writeInstruction('dd', g.immediateToStringInt(limit + 1), g.immediateToStringInt(0));
    g.writeLabelLong(LABEL_POOL_FLOAT_CONTENT);
    representer := RealValueRepresenter.create(RealValueRepresenter.FLOAT_SIGNIFICAND_DIGITS,
            RealValueRepresenter.FLOAT_ORDER_DIGITS);
    try
        for i := 0 to limit do begin
            floatValue := realToFloat(poolOfReal.getValue(i));
            shex := g.immediateToStringInt(floatToIntBits(floatValue));
            sdec := representer.toString(floatValue);
            g.writeInstruction('dd', shex);
            g.writeCommentToLineEnd(sdec);
        end;
    finally
        representer.free();
    end;
    g.writeEmptyLine();
    {%endregion}

    {%region числа типа double, используемые программой }
    poolOfReal := programmeDoubles;
    limit := poolOfReal.getLength() - 1;
    g.writeEmptyLine();
    g.writeCommentToLineEnd('pool of double');
    g.writeLabelLong(LABEL_POOL_DOUBLE_LENGTH);
    g.writeInstruction('dd', g.immediateToStringInt(limit + 1), g.immediateToStringInt(0));
    g.writeLabelLong(LABEL_POOL_DOUBLE_CONTENT);
    representer := RealValueRepresenter.create(RealValueRepresenter.DOUBLE_SIGNIFICAND_DIGITS,
            RealValueRepresenter.DOUBLE_ORDER_DIGITS);
    try
        for i := 0 to limit do begin
            doubleValue := realToDouble(poolOfReal.getValue(i));
            shex := g.immediateToStringLong(doubleToLongBits(doubleValue));
            sdec := representer.toString(doubleValue);
            g.writeInstruction('dq', shex);
            g.writeCommentToLineEnd(sdec);
        end;
    finally
        representer.free();
    end;
    g.writeEmptyLine();
    {%endregion}

    {%region числа типа real, используемые программой }
    poolOfReal := programmeReals;
    limit := poolOfReal.getLength() - 1;
    g.writeEmptyLine();
    g.writeCommentToLineEnd('pool of real');
    g.writeLabelLong(LABEL_POOL_REAL_LENGTH);
    g.writeInstruction('dd', g.immediateToStringInt(limit + 1), g.immediateToStringInt(0));
    g.writeLabelLong(LABEL_POOL_REAL_CONTENT);
    representer := RealValueRepresenter.create(RealValueRepresenter.REAL_SIGNIFICAND_DIGITS,
            RealValueRepresenter.REAL_ORDER_DIGITS);
    try
        for i := 0 to limit do begin
            realValue := poolOfReal.getValue(i);
            exponent := realExtractExponent(realValue);
            significand := realExtractSignificand(realValue);
            sdec := representer.toString(realValue);
            g.writeInstruction('dw', String_Array1d_create([
                g.immediateToStringShort(significand.shorts[0]),
                g.immediateToStringShort(significand.shorts[1]),
                g.immediateToStringShort(significand.shorts[2]),
                g.immediateToStringShort(significand.shorts[3]),
                g.immediateToStringShort(exponent)
            ]));
            g.writeCommentToLineEnd(sdec);
        end;
    finally
        representer.free();
    end;
    g.writeEmptyLine();
    {%endregion}

    {%region строки типа char[], используемые программой }
    limit := poolOfString.getLength() - 1;
    g.writeEmptyLine();
    g.writeCommentToLineEnd('pool of string');
    g.writeAlignGlobal(4);
    g.writeLabelLong(LABEL_POOL_STRING_LENGTH);
    g.writeInstruction('dd', g.immediateToStringInt(limit + 1));
    g.writeLabelLong(LABEL_POOL_STRING_CONTENT);
    for i := 0 to limit do begin
        g.writeInstruction('dd', g.immediateToStringInt(length(poolOfString.getValue(i))),
                g.labelRelativeToString(LABEL_POOL_STRING_ENTRY + intToString(i), -4))
    end;
    for i := 0 to limit do begin
        g.writeLabelLong(LABEL_POOL_STRING_ENTRY + intToString(i));
        stringValue := poolOfString.getValue(i);
        len := length(stringValue);
        j := 0;
        while j < len do begin
            k := len - j;
            if k >= 8 then begin
                schars := String_Array1d_create([
                    g.immediateToStringShort(int(stringValue[j + 1])),
                    g.immediateToStringShort(int(stringValue[j + 2])),
                    g.immediateToStringShort(int(stringValue[j + 3])),
                    g.immediateToStringShort(int(stringValue[j + 4])),
                    g.immediateToStringShort(int(stringValue[j + 5])),
                    g.immediateToStringShort(int(stringValue[j + 6])),
                    g.immediateToStringShort(int(stringValue[j + 7])),
                    g.immediateToStringShort(int(stringValue[j + 8]))
                ]);
            end else begin
                schars := String_Array1d_create(k);
                for l := 1 to k do begin
                    schars[l - 1] := g.immediateToStringShort(int(stringValue[j + l]));
                end;
            end;
            g.writeInstruction('dw', schars);
            inc(j, 8);
        end;
    end;
    g.writeEmptyLine();
    {%endregion}
end;

function TranslatorBuilderOf32bitCode.insertArguments(args: TypeFunction; offset: int): int;
var
    i: int;
    delta: int;
    g: TextGenerator;
begin
    result := 0;
    g := self.generator;
    for i := args.getArgumentsCount() - 1 downto 0 do with args.getArgument(i) do begin
        g.writeLabelRelative('.' + encode(name), EBP, offset);
        delta := dataType.getAlignedSize(TranslatorType.SIZE_32_BIT);
        inc(offset, delta);
        inc(result, delta);
    end;
end;

function TranslatorBuilderOf32bitCode.insertLocalVars(tree: SyntaxTree; offset: int): int;
var
    csize: int;
    lsize: int;
    locals: Hashtable;
    root: SyntaxNode;
    node: SyntaxNode;
    enum: NodeEnumerator;
    vars: Enumeration;
    g: TextGenerator;
    ltype: TypeDescriptor;
    lname: UnicodeString;
begin
    result := 0;
    if tree = nil then begin
        exit;
    end;
    locals := Hashtable.create();
    try
        root := tree.root as SyntaxNode;
        { определяем размер каждой локальной переменной }
        node := root;
        enum := root.enumerateChildrens();
        repeat
            case node.value of
            TranslatorTreeBuilder.OPERATOR_VARIABLE, TranslatorTreeBuilder.BLOCK_WITH: begin
                with node.associate as LocalVariable do begin
                    ltype := dataType;
                    lname := name;
                end;
                csize := ltype.getAlignedSize(TranslatorType.SIZE_32_BIT);
                if locals.containsKey(lname) then begin
                    lsize := (locals.get(lname) as IntegerAsObject).intValue();
                    if csize > lsize then begin
                        locals.put(lname, csize);
                    end;
                end else begin
                    locals.put(lname, csize);
                end;
            end;
            end;
            node := enum.nextChild() as SyntaxNode;
        until node = nil;
        { определяем смещение каждой локальной переменной }
        g := self.generator;
        vars := locals.keys();
        while vars.hasMoreElements() do begin
            lname := (vars.nextElement() as UnicodeStringAsObject).unicodeStringValue();
            lsize := (locals.get(lname) as IntegerAsObject).intValue();
            dec(offset, lsize);
            inc(result, lsize);
            g.writeLabelRelative('.' + encode(lname), EBP, offset);
        end;
    finally
        locals.free();
    end;
end;

function TranslatorBuilderOf32bitCode.getMemoryLocation(node: SyntaxNode; stack: RegisterStack;
        hasValueForWrite: boolean): MemoryLocation;
var
    regPtr: int;
    regIdx: int;
    regSrc: int;
    scale: int;
    size: int;
    nodeValue: int;
    g: TextGenerator;
    srIdx: String;
begin
    g := self.generator;
    nodeValue := node.value;
    if hasValueForWrite then begin
        case nodeValue of
        TranslatorTreeBuilder.EXPR_LOCAL_VARIABLE,
        TranslatorTreeBuilder.EXPR_GLOBAL_VARIABLE: begin
            regPtr := -1;
            regIdx := -1;
            regSrc := stack.getRegAt(0);
            stack.popRegs(1);
        end;
        TranslatorTreeBuilder.EXPR_ARRAY: begin
            regPtr := stack.getRegAt(2);
            regIdx := stack.getRegAt(1);
            regSrc := stack.getRegAt(0);
            stack.popRegs(3);
        end;
        TranslatorTreeBuilder.EXPR_FIELD: begin
            regPtr := stack.getRegAt(1);
            regIdx := -1;
            regSrc := stack.getRegAt(0);
            stack.popRegs(2);
        end;
        else
            exit;
        end;
    end else begin
        case nodeValue of
        TranslatorTreeBuilder.EXPR_LOCAL_VARIABLE,
        TranslatorTreeBuilder.EXPR_GLOBAL_VARIABLE: begin
            regPtr := -1;
            regIdx := -1;
            regSrc := -1;
        end;
        TranslatorTreeBuilder.EXPR_ARRAY: begin
            regPtr := stack.getRegAt(1);
            regIdx := stack.getRegAt(0);
            regSrc := -1;
            stack.popRegs(2);
        end;
        TranslatorTreeBuilder.EXPR_FIELD: begin
            regPtr := stack.getRegAt(0);
            regIdx := -1;
            regSrc := -1;
            stack.popRegs(1);
        end;
        else
            exit;
        end;
    end;
    case nodeValue of
    TranslatorTreeBuilder.EXPR_LOCAL_VARIABLE: begin
        result := MemoryLocationTfasm.create(g, regSrc,
                '.' + encode((node.associate as LocalVariable).name));
    end;
    TranslatorTreeBuilder.EXPR_GLOBAL_VARIABLE: begin
        result := MemoryLocationTfasm.create(g, regSrc,
                getEntryFullName(node.associate as GlobalVariable));
    end;
    TranslatorTreeBuilder.EXPR_FIELD: begin
        result := MemoryLocationTfasm.create(g, regSrc, regPtr,
                getFieldFullName(node.associate as StructureField));
    end;
    TranslatorTreeBuilder.EXPR_ARRAY: begin
        g.writeInstruction('call', FUNCTION_CHECK_ARRAY_INDEX);
        srIdx := g.registerToString(regIdx);
        size := node.dataType.size;
        case size of
        1, 2, 4, 8:
            scale := size;
        else
            scale := 1;
            g.writeInstruction('imul', srIdx, srIdx, g.immediateToString(size));
        end;
        result := MemoryLocationTfasm.create(g, regSrc, regPtr, regIdx, scale, '');
    end;
    else
        result := nil;
    end;
end;

end.