{
Этот исходный текст является частью Продвинутого векторного транслятора.
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.