{
Набор генераторов кода для языка программирования
Объектно-ориентированный продвинутый векторный транслятор
Copyright © 2021, 2024, 2026 Малик Разработчик
Это свободная программа: вы можете перераспространять ее и/или изменять
ее на условиях Стандартной общественной лицензии GNU в том виде,
в каком она была опубликована Фондом свободного программного обеспечения;
либо версии 3 лицензии, либо (по вашему выбору) любой более поздней версии.
Эта программа распространяется в надежде, что она будет полезной,
но БЕЗО ВСЯКИХ ГАРАНТИЙ; даже без неявной гарантии ТОВАРНОГО ВИДА
или ПРИГОДНОСТИ ДЛЯ ОПРЕДЕЛЕННЫХ ЦЕЛЕЙ. Подробнее см. в Стандартной
общественной лицензии GNU.
Вы должны были получить копию Стандартной общественной лицензии GNU
вместе с этой программой. Если это не так, см.
<https://www.gnu.org/licenses/>.
}
unit ru.malik.elaborarer.avtoo.generator;
{$MODE OBJFPC}
{$MODESWITCH TYPEHELPERS}
interface
{%region} uses
pascalx.lang,
pascalx.lang.math.avo,
pascalx.lang.math.vcoverage,
pascalx.lang.table,
pascalx.io,
pascalx.io.bytearray,
pascalx.io.charset,
platform.independent.filesystem,
platform.independent.osservices,
platform.independent.streamformat,
platform.independent.streamformat.compression.zlib,
ru.malik.elaborarer.avtoo.lang,
ru.malik.elaborarer.avtoo.compiler;
{%endregion}
{$TYPEINFO ON}
{$CALLING REGISTER}
const UNIT_NAME = 'ru.malik.elaborarer.avtoo.generator';
{%region} type
ResourceLocation = class;
CodeGenerator = class;
BinarySourceGenerator = class;
AssemblerElementWriter = class;
AssemblerSourcePrintStream = class;
AssemblerSourceGenerator = class;
ResourceLocation = class(&Object)
strict private
fldLibrary: &Library;
fldRelativePath: UnicodeString;
fldDestinationPath: UnicodeString;
public
constructor create(__library: &Library; const __relativePath: UnicodeString);
property &library: ru.malik.elaborarer.avtoo.lang.&Library read fldLibrary;
property relativePath: UnicodeString read fldRelativePath;
property destinationPath: UnicodeString read fldDestinationPath write fldDestinationPath;
end;
CodeGenerator = class abstract(ImmediateBuilder)
strict private
class procedure clearDirectory(fileSystem: FileSystem; const directoryPath: UnicodeString); static;
public
class procedure createImmediateDirectories(fileSystem: FileSystem; const directoryPath, relativePath: UnicodeString); static;
class function prepareDestinationPath(fileSystem: FileSystem; const destinationPath: UnicodeString): UnicodeString; static;
protected
function getOverwritten(): UnicodeString; virtual; abstract;
function isStaticFieldsOnly(): boolean; override; final;
function isLibrary(): boolean; override; final;
public
constructor create(__library: boolean);
property overwritten: UnicodeString read getOverwritten;
end;
BinarySourceGenerator = class(CodeGenerator)
strict private type
HashtableOfAnsiStringToObjectVector = specialize HashtableOfAnsiString<ObjectVector>;
strict private
class procedure appendClassType(__type: ClassType; constants, container: ObjectVector); static;
class procedure createRecompilable(container: ObjectVector; fileSystem: FileSystem; const recompilablePath: UnicodeString); static;
class procedure fillSourcesTable(table: HashtableOfAnsiStringToObjectVector; sources: SourceArray); static;
class procedure freeSourcesTable(table: HashtableOfAnsiStringToObjectVector); static;
public const
{ уровни создания файлов двоичного исходного кода }
LEVEL_CLASS = int(0);
LEVEL_PACKAGE = int(1);
LEVEL_LIBRARY = int(2);
strict private
fldLevel: int;
fldOverwritten: UnicodeString;
procedure setLevel(newLevel: int);
protected
function getOverwritten(): UnicodeString; override; final;
public
constructor create();
procedure compile(); override;
property level: int read fldLevel write setLevel;
end;
AssemblerElementWriter = class(AVTOOConstants)
public const
{ флаги формирования сигнатуры типа }
NORM = int(0);
WEAK = int(1);
STACK = int(2);
protected
fldOffset: int;
fldText: char_Array1d;
public
procedure trim(); virtual;
function get(): AnsiString; virtual;
function &set(const text: char_Array1d; offset: int): AssemblerElementWriter; virtual;
function writeChar(character: char): AssemblerElementWriter; virtual;
function writeLabel(character: char; &label: int): AssemblerElementWriter; virtual;
function writeLabel(&label: int): AssemblerElementWriter; virtual;
function writeOffset(value: int): AssemblerElementWriter; virtual;
function writeByte(value: int): AssemblerElementWriter; virtual;
function writeShort(value: int): AssemblerElementWriter; virtual;
function writeInt(value: int): AssemblerElementWriter; virtual;
function writeLong(value: long): AssemblerElementWriter; virtual;
function writeDecimal(value: int): AssemblerElementWriter; virtual;
function writeString(const &string: AnsiString): AssemblerElementWriter; virtual;
function writeString(const &string: AnsiString; beginIndex, endIndex: int): AssemblerElementWriter; virtual;
function writeLabel(node: Node): AssemblerElementWriter; virtual;
function writeSignature(kind, flags: int): AssemblerElementWriter; virtual;
function writeSignature(&type: &Type; flags: int): AssemblerElementWriter; virtual;
function &set(const text: char_Array1d): AssemblerElementWriter;
property offset: int read fldOffset write fldOffset;
end;
AssemblerSourcePrintStream = class(&Object, DataEncoder, CharsetOutputAdapter, OutputAdapter, MutableDataHolder, DataHolder)
strict private
class var defaultEncoder: CharEncoder;
class function getSeparator(state: int): AnsiString; static;
private
class procedure initialize(); static;
class procedure finalize(); static;
strict private
fldState: int;
fldMargin: int;
fldText: AnsiString;
fldSpaces: char_Array1d;
fldEncoder: CharEncoder;
procedure write(const src: char);
procedure write(const src: AnsiString);
function spaces(count: int): AnsiString;
public
constructor create();
constructor create(encoder: CharEncoder);
procedure saveToOutputStream(stream: ByteWriter); virtual;
procedure saveToOutputStream(stream: ByteWriter; encoder: CharEncoder); virtual;
procedure clear(); virtual;
procedure increaseMargin(); virtual;
procedure decreaseMargin(); virtual;
procedure print(const src: AnsiString); virtual;
procedure printHeader(const header: AnsiString); virtual;
procedure printLabel(const &label: AnsiString); virtual;
procedure printInstruction(const mnemonic: AnsiString); virtual;
procedure printInstruction(const mnemonic, operand: AnsiString); virtual;
procedure printInstruction(const mnemonic: AnsiString; const operands: AnsiString_Array1d; offset, length: int); virtual;
procedure printContinuation(const operands: AnsiString_Array1d; offset, length: int); virtual;
procedure println(); virtual;
procedure println(const src: AnsiString); virtual;
procedure printlnHeader(const header: AnsiString); virtual;
procedure printlnLabel(const &label: AnsiString); virtual;
procedure printlnInstruction(const mnemonic: AnsiString); virtual;
procedure printlnInstruction(const mnemonic, operand: AnsiString); virtual;
procedure printlnInstruction(const mnemonic: AnsiString; const operands: AnsiString_Array1d; offset, length: int); virtual;
procedure printlnContinuation(const operands: AnsiString_Array1d; offset, length: int); virtual;
function isEmpty(): boolean; virtual;
end;
AssemblerSourceGenerator = class(CodeGenerator)
strict private type
HashtableOfAnsiStringToType = specialize HashtableOfAnsiString<&Type>;
HashtableOfUnicodeStringToLibrary = specialize HashtableOfUnicodeString<&Library>;
protected type
HashtableOfUnicodeStringToResourceLocation = specialize HashtableOfUnicodeString<ResourceLocation>;
protected const
{ флаги формирования сигнатуры типа }
NORM = AssemblerElementWriter.NORM;
WEAK = AssemblerElementWriter.WEAK;
STACK = AssemblerElementWriter.STACK;
{ длина буфера для копирования ресурсов }
COPY_BUFFER_LENGTH = int($8000);
protected
class procedure setResourceLocation(table: HashtableOfUnicodeStringToResourceLocation; const name: UnicodeString; newLocation: ResourceLocation); static;
class procedure clearResourcesTable(table: HashtableOfUnicodeStringToResourceLocation); static;
class procedure freeResourcesTable(table: HashtableOfUnicodeStringToResourceLocation); static;
class function isTypeCastAvailable(kindBaseOfSrc, lengthOfSrc, kindBaseOfNew, lengthOfNew: int): boolean; static;
class function toRuntimePrimitiveKind(kind: int): int; static;
class function getNeedRegisterTypeKind(node: Node): int; static;
class function getPayLength(const aarray: char_Array1d): int; static;
class function getPayLengthPtr(const aarray): int; static;
class function toString(const aarray: char_Array1d): AnsiString; overload; static;
class function getTypedItem(itemC: Constant; itemI: TableItem): TypedItem; static;
strict private
fldReflect: boolean;
fldOverwritten: UnicodeString;
fldDestinationName: UnicodeString;
fldGlobalWriter: AssemblerElementWriter;
fldSourcesTable: HashtableOfUnicodeStringToLibrary;
procedure findSourcesIn(__library: &Library);
procedure findSourcesIn(__library: &Library; const __relativePath: UnicodeString);
procedure constantToFasmString(value: Constant; const operand: char_Array1d);
function additionalToFasmString(operandC: Constant; operandI: TableItem; const operand: char_Array1d): AnsiString;
function additionalToFasmString(operandC: Constant; operandI: TableItem; const operand: char_Array1d; refsLocalTable: HashtableOfAnsiStringToType): AnsiString;
protected
fldRealStorage: RealStorage;
fldDoubleStorage: DoubleStorage;
fldDouble2Storage: Double2Storage;
fldDouble4Storage: Double4Storage;
fldDouble8Storage: Double8Storage;
fldFloatStorage: FloatStorage;
fldFloat2Storage: Float2Storage;
fldFloat4Storage: Float4Storage;
fldFloat8Storage: Float8Storage;
fldByte2Storage: Byte2Storage;
fldByte4Storage: Byte4Storage;
fldByte8Storage: Byte8Storage;
fldShort2Storage: Short2Storage;
fldShort4Storage: Short4Storage;
fldShort8Storage: Short8Storage;
fldInt2Storage: Int2Storage;
fldInt4Storage: Int4Storage;
fldInt8Storage: Int8Storage;
fldLongStorage: LongStorage;
fldLong2Storage: Long2Storage;
fldLong4Storage: Long4Storage;
fldLong8Storage: Long8Storage;
fldStringStorage: UnicodeStringStorage;
fldDebugInfoSources: UnicodeStringStorage;
fldDebugInfoStrings: AnsiStringStorage;
fldResourcesTable: HashtableOfUnicodeStringToResourceLocation;
procedure findResourcesIn(__library: &Library); virtual;
procedure findResourcesIn(__library: &Library; const __relativePath: UnicodeString); virtual;
procedure generatePackageData(__pack, __next: Package; output: AssemblerSourcePrintStream); virtual;
procedure generatePrimitiveData(__type: PrimitiveType; output: AssemblerSourcePrintStream); virtual;
procedure generateClassData(__type: ClassType; output: AssemblerSourcePrintStream); virtual;
procedure generateClassCode(__type: ClassType; output: AssemblerSourcePrintStream); virtual;
procedure generateCallableCode(__callable: Callable; output: AssemblerSourcePrintStream); virtual;
procedure generateImplementorCode(__type, __superservice: ClassType; output: AssemblerSourcePrintStream); virtual;
procedure generateConstants(output: AssemblerSourcePrintStream); virtual;
procedure generateDebugInfoEntries(output: AssemblerSourcePrintStream); virtual;
procedure generateDebugInfoSources(output: AssemblerSourcePrintStream); virtual;
procedure generateDebugInfoStrings(output: AssemblerSourcePrintStream); virtual;
procedure generateProgramme(output: AssemblerSourcePrintStream); virtual;
function newAssemblerElementWriter(): AssemblerElementWriter; virtual;
function newAssemblerSourcePrintStream(): AssemblerSourcePrintStream; virtual;
function getOverwritten(): UnicodeString; override; final;
function getAssemblerElementWriter(): AssemblerElementWriter;
public
constructor create(__reflect: boolean; const __destinationName: UnicodeString);
destructor destroy; override;
procedure afterConstruction(); override;
procedure beforeDestruction(); override;
procedure compile(); override;
procedure clear(); override;
property reflect: boolean read fldReflect;
property destinationName: UnicodeString read fldDestinationName;
end;
{%endregion}
implementation
{$R *.res}
{$INLINE ON}
{$TYPEINFO OFF}
{$CALLING REGISTER}
{%region} type
BinarySourceGeneratorConstants = class;
BinarySourceGeneratorConstants = class(ObjectVector)
public
class function serializeVersion(): ByteArrayOutputStream; static;
class function serializeTextSource(source: TextSource; charset: Charset): ByteArrayOutputStream; static;
class function serializeEnd(): ByteArrayOutputStream; static;
strict private
procedure removeAllElements();
function getOperandIndex(operandC: Constant; operandI: TableItem; thisArgument: Local): int;
function indexOf(const item: AnsiString): int; overload;
function indexAcquire(const item: AnsiString): int;
function indexAcquire(const item: UnicodeString): int;
function indexAcquire(const item: TableItem): int;
function indexAcquire(const item: TypedMember): int;
function indexAcquire(const item: Constant): int;
public
constructor create();
destructor destroy; override;
procedure afterConstruction(); override;
procedure clear(); override;
function serializeConstants(charset: Charset): ByteArrayOutputStream;
function serializePackage(__pack: Package): ByteArrayOutputStream;
function serializeClassType(__type: ClassType): ByteArrayOutputStream;
function serializeClassField(__field: Field): ByteArrayOutputStream;
function serializeStructField(__field: Field): ByteArrayOutputStream;
function serializeProperty(__property: &Property): ByteArrayOutputStream;
function serializeCallable(__callable: Callable): ByteArrayOutputStream;
function serializeMethod(__method: Method): ByteArrayOutputStream;
function serializeCode(__code: Code): ByteArrayOutputStream;
end;
BinarySourceGeneratorCodeDataOutput = type helper for DataOutput
public
procedure writeByte2(const value: byte2);
procedure writeByte4(const value: byte4);
procedure writeByte8(const value: byte8);
procedure writeShort2(const value: short2);
procedure writeShort4(const value: short4);
procedure writeShort8(const value: short8);
procedure writeInt2(const value: int2);
procedure writeInt4(const value: int4);
procedure writeInt8(const value: int8);
procedure writeLong2(const value: long2);
procedure writeLong4(const value: long4);
procedure writeLong8(const value: long8);
procedure writeFloat2(const value: float2);
procedure writeFloat4(const value: float4);
procedure writeFloat8(const value: float8);
procedure writeDouble2(const value: double2);
procedure writeDouble4(const value: double4);
procedure writeDouble8(const value: double8);
procedure writeIndex(index: int);
procedure writeLabel(target: Node);
end;
AssemblerSourceGeneratorClassType = class helper for ClassType
public
function hasOverriddingMembersFor(superservice: ClassType; isSuperclassesLook: boolean): boolean;
end;
{%endregion}
{%region ResourceLocation }
constructor ResourceLocation.create(__library: &Library; const __relativePath: UnicodeString);
begin
inherited create();
fldLibrary := __library;
fldRelativePath := __relativePath;
end;
{%endregion}
{%region CodeGenerator }
class procedure CodeGenerator.clearDirectory(fileSystem: FileSystem; const directoryPath: UnicodeString);
var
index: int;
dir: UnicodeString;
oname: UnicodeString;
dirs: ObjectVector;
files: ObjectVector;
begin
dirs := nil;
files := nil;
try
dirs := ObjectVector.create(true);
files := ObjectVector.create(true);
with fileSystem.findFirst(directoryPath) do try
repeat
oname := name;
if (oname <> '.') and (oname <> '..') then begin
if directory then begin
dirs.append(CoUnicodeString.create(oname));
end else begin
files.append(CoUnicodeString.create(oname));
end;
end;
until not findNext();
finally
close();
end;
for index := 0 to dirs.getLength() - 1 do begin
dir := directoryPath + CoUnicodeString(dirs.readComponent(index)).asUnicodeString();
clearDirectory(fileSystem, dir + '/');
fileSystem.deleteDirectory(dir);
end;
for index := 0 to files.getLength() - 1 do begin
fileSystem.deleteFile(directoryPath + CoUnicodeString(files.readComponent(index)).asUnicodeString());
end;
finally
dirs.free();
files.free();
end;
end;
class procedure CodeGenerator.createImmediateDirectories(fileSystem: FileSystem; const directoryPath, relativePath: UnicodeString);
var
index: int;
directoryName: UnicodeString;
attributes: ObjectAttributes;
begin
if fileSystem = nil then begin
fileSystem := FileSystemRoot.get(Process.current().workingDirectory).fileSystem;
end;
attributes := ObjectAttributes.create(fileSystem);
try
index := 0;
repeat
index := relativePath.indexOf('/', index + 1);
if index < 1 then break;
directoryName := directoryPath + relativePath.substring(1, index);
if fileSystem.isObjectExists(directoryName) then begin
fileSystem.readAttributes(directoryName, attributes);
if not attributes.directory then fileSystem.createDirectory(directoryName);
continue;
end;
fileSystem.createDirectory(directoryName);
until false;
finally
attributes.free();
end;
end;
class function CodeGenerator.prepareDestinationPath(fileSystem: FileSystem; const destinationPath: UnicodeString): UnicodeString;
var
path: UnicodeString;
attributes: ObjectAttributes;
begin
if fileSystem = nil then begin
fileSystem := FileSystemRoot.get(Process.current().workingDirectory).fileSystem;
end;
if not fileSystem.isObjectExists(destinationPath) then begin
fileSystem.createDirectory(destinationPath);
result := destinationPath + '/';
exit;
end;
attributes := ObjectAttributes.create(fileSystem);
try
fileSystem.readAttributes(destinationPath, attributes);
if not attributes.directory then begin
fileSystem.createDirectory(destinationPath);
result := destinationPath + '/';
exit;
end;
finally
attributes.free();
end;
path := destinationPath + '/';
clearDirectory(fileSystem, path);
result := path;
end;
function CodeGenerator.isStaticFieldsOnly(): boolean;
begin
result := false;
end;
function CodeGenerator.isLibrary(): boolean;
begin
result := inherited isLibrary();
end;
constructor CodeGenerator.create(__library: boolean);
begin
inherited create(false, __library);
end;
{%endregion}
{%region BinarySourceGenerator }
class procedure BinarySourceGenerator.appendClassType(__type: ClassType; constants, container: ObjectVector);
label
break_label0;
var
index: int;
isStruct: boolean;
__code: Code;
__member: Member;
__method: Method;
__callable: Callable;
__constants: BinarySourceGeneratorConstants absolute constants;
begin
container.append(__constants.serializeClassType(__type));
isStruct := __type.isStruct();
for index := 0 to __type.getLength() - 1 do begin
__code := nil;
begin
__member := __type.readComponent(index);
if __member is Method then begin
__method := Method(__member);
__code := __method.code;
container.append(__constants.serializeMethod(__method));
goto break_label0;
end;
if __member is Callable then begin
__callable := Callable(__member);
__code := __callable.code;
container.append(__constants.serializeCallable(__callable));
goto break_label0;
end;
if __member is &Property then begin
container.append(__constants.serializeProperty(&Property(__member)));
continue;
end;
if __member is Field then begin
if isStruct then begin
container.append(__constants.serializeStructField(Field(__member)));
continue;
end;
container.append(__constants.serializeClassField(Field(__member)));
end;
continue;
end;
break_label0:
if __code <> nil then container.append(__constants.serializeCode(__code));
end;
end;
class procedure BinarySourceGenerator.createRecompilable(container: ObjectVector; fileSystem: FileSystem; const recompilablePath: UnicodeString);
type
ByteArrayOutputStream_Array1d = specialize DynamicArray<ByteArrayOutputStream>;
var
cindex: int;
dlength: int;
dbytes: byte_Array1d;
chunks: ByteArrayOutputStream_Array1d;
stream: ByteWriter;
begin
chunks := ByteArrayOutputStream_Array1d(container.clone());
stream := fileSystem.createFile(recompilablePath + BINARY_SOURCE_EXTENSION);
try
with DataOutputStream.create(stream), bigEndianDataOutput do try
with Checksum32(CRC32.create()) do try
writeLong(AVTOORecompilable.SIGNATURE_AVTR);
for cindex := 0 to system.length(chunks) - 1 do begin
dbytes := chunks[cindex].toByteArray();
dlength := system.length(dbytes);
update(dbytes, 0, dlength);
writeInt((dlength - 4) shr 1);
write(dbytes);
writeInt(getValue());
reset();
end;
finally
free();
end;
finally
free();
end;
stream.flush();
finally
stream.close();
end;
end;
class procedure BinarySourceGenerator.fillSourcesTable(table: HashtableOfAnsiStringToObjectVector; sources: SourceArray);
var
index: int;
name: AnsiString;
owner: Package;
source: TextSource;
vector: ObjectVector;
begin
for index := sources.getLength() - 1 downto 0 do begin
source := TextSource(Lang.cast(sources.readComponent(index), TextSource));
owner := source.owner;
if owner = nil then continue;
name := owner.specialCanonicalName;
if table.contains(name) then begin
vector := table[name];
end else begin
vector := ObjectVector.create(false);
table[name] := vector;
end;
vector.append(source);
end;
end;
class procedure BinarySourceGenerator.freeSourcesTable(table: HashtableOfAnsiStringToObjectVector);
var
index: int;
key: AnsiString;
value: TObject;
begin
for index := table.length - 1 downto 0 do begin
key := table.keyAt(index);
value := table[key];
table[key] := nil;
value.free();
end;
table.free();
end;
procedure BinarySourceGenerator.setLevel(newLevel: int);
begin
if newLevel < LEVEL_CLASS then newLevel := LEVEL_CLASS;
if newLevel > LEVEL_LIBRARY then newLevel := LEVEL_LIBRARY;
fldLevel := newLevel;
end;
function BinarySourceGenerator.getOverwritten(): UnicodeString;
begin
result := fldOverwritten;
end;
constructor BinarySourceGenerator.create();
begin
inherited create(true);
fldLevel := LEVEL_CLASS;
end;
procedure BinarySourceGenerator.compile();
type
TextSource_Array1d = specialize DynamicArray<TextSource>;
var
dindex: int;
pindex: int;
sindex: int;
packageName: AnsiString;
directoryPath: UnicodeString;
destinationPath: UnicodeString;
chunkEnd: byte_Array1d;
chunkVersion: byte_Array1d;
sourcesArray: TextSource_Array1d;
pack: Package;
utf16: Charset;
source: TextSource;
__project: ru.malik.elaborarer.avtoo.lang.&Library;
container: ObjectVector;
__fileSystem: FileSystem;
declared: ClassTypeArray;
sourcesList: ObjectVector;
constants: BinarySourceGeneratorConstants;
__type: ru.malik.elaborarer.avtoo.lang.ClassType;
sourcesTable: HashtableOfAnsiStringToObjectVector;
begin
{ -- предыдущие стадии -- }
inherited compile();
{ 8. Стадия выгрузки данных }
utf16 := Charset.get('UTF-16 BE');
__project := project;
__fileSystem := __project.fileSystem;
destinationPath := prepareDestinationPath(__fileSystem, __project.directoryPath + BINARY_SOURCE_PATH);
fldOverwritten := destinationPath;
container := nil;
constants := nil;
try
container := ObjectVector.create(true);
constants := BinarySourceGeneratorConstants.create();
with BinarySourceGeneratorConstants.serializeVersion() do try
chunkVersion := toByteArray();
finally
free();
end;
with BinarySourceGeneratorConstants.serializeEnd() do try
chunkEnd := toByteArray();
finally
free();
end;
case fldLevel of
LEVEL_LIBRARY: begin
container.append(ByteArrayOutputStream.create(chunkVersion));
sourcesTable := HashtableOfAnsiStringToObjectVector.create();
try
fillSourcesTable(sourcesTable, __project.sources);
for pindex := 0 to __project.getLength() - 1 do begin
pack := __project.readComponent(pindex);
packageName := pack.specialCanonicalName;
if packageName.length <= 0 then continue;
sourcesList := sourcesTable[packageName];
sourcesArray := nil;
if sourcesList <> nil then sourcesArray := TextSource_Array1d(sourcesList.clone());
container.append(constants.serializePackage(pack));
if sourcesArray <> nil then for sindex := 0 to system.length(sourcesArray) - 1 do begin
source := sourcesArray[sindex];
container.append(BinarySourceGeneratorConstants.serializeTextSource(source, utf16));
declared := source.declared;
for dindex := 0 to declared.getLength() - 1 do begin
appendClassType(declared.readComponent(dindex), constants, container);
end;
end;
end;
finally
freeSourcesTable(sourcesTable);
end;
container.insert(1, constants.serializeConstants(utf16));
container.append(ByteArrayOutputStream.create(chunkEnd));
createRecompilable(container, __fileSystem, destinationPath + '!library');
container.clear();
constants.clear();
end;
LEVEL_PACKAGE: begin
sourcesTable := HashtableOfAnsiStringToObjectVector.create();
try
fillSourcesTable(sourcesTable, __project.sources);
for pindex := 0 to __project.getLength() - 1 do begin
pack := __project.readComponent(pindex);
packageName := pack.specialCanonicalName;
if packageName.length <= 0 then continue;
sourcesList := sourcesTable[packageName];
sourcesArray := nil;
if sourcesList <> nil then sourcesArray := TextSource_Array1d(sourcesList.clone());
container.append(ByteArrayOutputStream.create(chunkVersion));
container.append(constants.serializePackage(pack));
if sourcesArray <> nil then for sindex := 0 to system.length(sourcesArray) - 1 do begin
source := sourcesArray[sindex];
container.append(BinarySourceGeneratorConstants.serializeTextSource(source, utf16));
declared := source.declared;
for dindex := 0 to declared.getLength() - 1 do begin
appendClassType(declared.readComponent(dindex), constants, container);
end;
end;
container.insert(1, constants.serializeConstants(utf16));
container.append(ByteArrayOutputStream.create(chunkEnd));
createRecompilable(container, __fileSystem, destinationPath + packageName.toUTF16());
container.clear();
constants.clear();
end;
finally
freeSourcesTable(sourcesTable);
end;
end;
else
for pindex := 0 to __project.getLength() - 1 do begin
pack := __project.readComponent(pindex);
packageName := pack.specialCanonicalName;
if packageName.length <= 0 then continue;
directoryPath := destinationPath + packageName.toUTF16();
__fileSystem.createDirectory(directoryPath);
directoryPath := directoryPath + '/';
begin
container.append(ByteArrayOutputStream.create(chunkVersion));
container.append(constants.serializePackage(pack));
container.insert(1, constants.serializeConstants(utf16));
container.append(ByteArrayOutputStream.create(chunkEnd));
createRecompilable(container, __fileSystem, directoryPath + '!package');
container.clear();
constants.clear();
end;
for dindex := 0 to pack.getLength() - 1 do begin
__type := pack.readComponent(dindex) as ru.malik.elaborarer.avtoo.lang.ClassType;
if __type is ArrayType then continue;
container.append(ByteArrayOutputStream.create(chunkVersion));
container.append(BinarySourceGeneratorConstants.serializeTextSource(TextSource(Lang.cast(__type.source, TextSource)), utf16));
appendClassType(__type, constants, container);
container.insert(1, constants.serializeConstants(utf16));
container.append(ByteArrayOutputStream.create(chunkEnd));
createRecompilable(container, __fileSystem, directoryPath + __type.specialSimpleName.toUTF16());
container.clear();
constants.clear();
end;
end;
end;
finally
container.free();
constants.free();
end;
end;
{%endregion}
{%region AssemblerElementWriter }
procedure AssemblerElementWriter.trim();
var
__offset: int;
text: char_Array1d;
begin
__offset := fldOffset;
text := fldText;
if (__offset >= 0) and (__offset < system.length(text)) then begin
text[__offset] := #0;
end;
end;
function AssemblerElementWriter.get(): AnsiString;
begin
result := AnsiString.create(fldText, 0, fldOffset);
end;
function AssemblerElementWriter.&set(const text: char_Array1d; offset: int): AssemblerElementWriter;
begin
fldText := text;
fldOffset := offset;
result := self;
end;
function AssemblerElementWriter.writeChar(character: char): AssemblerElementWriter;
var
__offset: int;
begin
__offset := fldOffset;
fldText[__offset] := character;
fldOffset := __offset + 1;
result := self;
end;
function AssemblerElementWriter.writeLabel(character: char; &label: int): AssemblerElementWriter;
var
index: int;
length: int;
__offset: int;
text: char_Array1d;
begin
length := 7;
if (&label >= $00010000) and (&label < $01000000) then begin
length := 9;
end else
if (&label >= $01000000) or (&label < $00000000) then begin
length := 11;
end;
__offset := fldOffset;
text := fldText;
text[__offset] := '.';
text[__offset + 2] := '.';
text[__offset + 1] := character;
inc(__offset, 3);
for index := 3 to length - 1 do begin
text[__offset] := CoChar.toUpperCase(CoChar.toChar((&label shr ((length - index - 1) shl 2)) and $0f));
inc(__offset);
end;
fldOffset := __offset;
result := self;
end;
function AssemblerElementWriter.writeLabel(&label: int): AssemblerElementWriter;
var
index: int;
length: int;
__offset: int;
text: char_Array1d;
begin
length := 7;
if (&label >= $00010000) and (&label < $01000000) then begin
length := 9;
end else
if (&label >= $01000000) or (&label < $00000000) then begin
length := 11;
end;
__offset := fldOffset;
text := fldText;
text[__offset] := '.';
inc(__offset);
text[__offset] := '$';
inc(__offset);
text[__offset + length - 3] := '$';
for index := 3 to length - 1 do begin
text[__offset] := CoChar.toChar((&label shr ((length - index - 1) shl 2)) and $0f);
inc(__offset);
end;
fldOffset := __offset + 1;
result := self;
end;
function AssemblerElementWriter.writeOffset(value: int): AssemblerElementWriter;
var
index: int;
length: int;
__offset: int;
text: char_Array1d;
begin
length := 2;
if (value >= $00000010) and (value < $00000100) then begin
length := 3;
end else
if (value >= $00000100) and (value < $00001000) then begin
length := 4;
end else
if (value >= $00001000) and (value < $00010000) then begin
length := 5;
end else
if (value >= $00010000) and (value < $00100000) then begin
length := 6;
end else
if (value >= $00100000) and (value < $01000000) then begin
length := 7;
end else
if (value >= $01000000) and (value < $10000000) then begin
length := 8;
end else
if (value >= $10000000) or (value < $00000000) then begin
length := 9;
end;
__offset := fldOffset;
text := fldText;
text[__offset] := '$';
inc(__offset);
for index := 1 to length - 1 do begin
text[__offset] := CoChar.toChar((value shr ((length - index - 1) shl 2)) and $0f);
inc(__offset);
end;
fldOffset := __offset;
result := self;
end;
function AssemblerElementWriter.writeByte(value: int): AssemblerElementWriter;
var
index: int;
__offset: int;
text: char_Array1d;
begin
__offset := fldOffset;
text := fldText;
text[__offset] := '$';
inc(__offset);
for index := 1 to 2 do begin
text[__offset] := CoChar.toChar(int(value shr ((2 - index) shl 2)) and $0f);
inc(__offset);
end;
fldOffset := __offset;
result := self;
end;
function AssemblerElementWriter.writeShort(value: int): AssemblerElementWriter;
var
index: int;
__offset: int;
text: char_Array1d;
begin
__offset := fldOffset;
text := fldText;
text[__offset] := '$';
inc(__offset);
for index := 1 to 4 do begin
text[__offset] := CoChar.toChar(int(value shr ((4 - index) shl 2)) and $0f);
inc(__offset);
end;
fldOffset := __offset;
result := self;
end;
function AssemblerElementWriter.writeInt(value: int): AssemblerElementWriter;
var
index: int;
__offset: int;
text: char_Array1d;
begin
__offset := fldOffset;
text := fldText;
text[__offset] := '$';
inc(__offset);
for index := 1 to 8 do begin
text[__offset] := CoChar.toChar(int(value shr ((8 - index) shl 2)) and $0f);
inc(__offset);
end;
fldOffset := __offset;
result := self;
end;
function AssemblerElementWriter.writeLong(value: long): AssemblerElementWriter;
var
index: int;
__offset: int;
text: char_Array1d;
begin
__offset := fldOffset;
text := fldText;
text[__offset] := '$';
inc(__offset);
for index := 1 to 16 do begin
text[__offset] := CoChar.toChar(int(value shr ((16 - index) shl 2)) and $0f);
inc(__offset);
end;
fldOffset := __offset;
result := self;
end;
function AssemblerElementWriter.writeDecimal(value: int): AssemblerElementWriter;
var
index: int;
length: int;
__offset: int;
text: char_Array1d;
begin
__offset := fldOffset;
text := fldText;
if value >= 0 then begin
value := -value;
end else begin
text[__offset] := '-';
inc(__offset);
end;
length := -1;
if (value > -100) and (value <= -10) then begin
length := -2;
end else
if (value > -1000) and (value <= -100) then begin
length := -3;
end else
if (value > -10000) and (value <= -1000) then begin
length := -4;
end else
if (value > -100000) and (value <= -10000) then begin
length := -5;
end else
if (value > -1000000) and (value <= -100000) then begin
length := -6;
end else
if (value > -10000000) and (value <= -1000000) then begin
length := -7;
end else
if (value > -100000000) and (value <= -10000000) then begin
length := -8;
end else
if (value > -1000000000) and (value <= -100000000) then begin
length := -9;
end else
if value <= -1000000000 then begin
length := -10;
end;
dec(__offset, length);
index := 0;
while index > length do begin
dec(index);
text[__offset + index] := char(int('0') - (value mod 10));
value := value div 10;
end;
fldOffset := __offset;
result := self;
end;
function AssemblerElementWriter.writeString(const &string: AnsiString): AssemblerElementWriter;
var
length: int;
__offset: int;
begin
__offset := fldOffset;
length := &string.length;
&Array.copyRaw(&string[1], fldText[__offset], length * sizeof(char));
fldOffset := __offset + length;
result := self;
end;
function AssemblerElementWriter.writeString(const &string: AnsiString; beginIndex, endIndex: int): AssemblerElementWriter;
var
length: int;
__offset: int;
begin
__offset := fldOffset;
length := endIndex - beginIndex;
&Array.copyRaw(&string[beginIndex], fldText[__offset], length * sizeof(char));
fldOffset := __offset + length;
result := self;
end;
function AssemblerElementWriter.writeLabel(node: Node): AssemblerElementWriter;
var
&label: int;
begin
&label := node.debugIndex;
if &label >= 0 then begin
result := writeLabel('D', &label);
exit;
end;
result := writeLabel('L', node.labelIndex);
end;
function AssemblerElementWriter.writeSignature(kind, flags: int): AssemblerElementWriter;
var
signature: AnsiString;
begin
case kind of
TYP_REF: begin
if (flags and WEAK) <> 0 then begin
signature := 'w';
end else begin
signature := 'r';
end;
end;
TYP_CHAR: begin
if (flags and STACK) <> 0 then begin
signature := 'i';
end else begin
signature := 'c';
end;
end;
TYP_REAL: begin
signature := 'e';
end;
TYP_DOUBLE: begin
signature := 'd';
end;
TYP_DOUBLE2: begin
signature := 'd2';
end;
TYP_DOUBLE4: begin
signature := 'd4';
end;
TYP_DOUBLE8: begin
signature := 'd8';
end;
TYP_FLOAT: begin
signature := 'f';
end;
TYP_FLOAT2: begin
signature := 'f2';
end;
TYP_FLOAT4: begin
signature := 'f4';
end;
TYP_FLOAT8: begin
signature := 'f8';
end;
TYP_BOOLEAN,
TYP_BYTE: begin
if (flags and STACK) <> 0 then begin
signature := 'i';
end else begin
signature := 'b';
end;
end;
TYP_BYTE2: begin
signature := 'b2';
end;
TYP_BYTE4: begin
signature := 'b4';
end;
TYP_BYTE8: begin
signature := 'b8';
end;
TYP_SHORT: begin
if (flags and STACK) <> 0 then begin
signature := 'i';
end else begin
signature := 's';
end;
end;
TYP_SHORT2: begin
signature := 's2';
end;
TYP_SHORT4: begin
signature := 's4';
end;
TYP_SHORT8: begin
signature := 's8';
end;
TYP_INT: begin
signature := 'i';
end;
TYP_INT2: begin
signature := 'i2';
end;
TYP_INT4: begin
signature := 'i4';
end;
TYP_INT8: begin
signature := 'i8';
end;
TYP_LONG: begin
signature := 'l';
end;
TYP_LONG2: begin
signature := 'l2';
end;
TYP_LONG4: begin
signature := 'l4';
end;
TYP_LONG8: begin
signature := 'l8';
end;
else
signature := '';
end;
result := writeString(signature);
end;
function AssemblerElementWriter.writeSignature(&type: &Type; flags: int): AssemblerElementWriter;
var
signature: AnsiString;
begin
case &type.kind of
TYP_REF: begin
if (flags and WEAK) <> 0 then begin
signature := 'w';
end else begin
signature := 'r';
end;
end;
TYP_CHAR: begin
if (flags and STACK) <> 0 then begin
signature := 'i';
end else begin
signature := 'c';
end;
end;
TYP_REAL: begin
signature := 'e';
end;
TYP_DOUBLE: begin
signature := 'd';
end;
TYP_DOUBLE2: begin
signature := 'd2';
end;
TYP_DOUBLE4: begin
signature := 'd4';
end;
TYP_DOUBLE8: begin
signature := 'd8';
end;
TYP_FLOAT: begin
signature := 'f';
end;
TYP_FLOAT2: begin
signature := 'f2';
end;
TYP_FLOAT4: begin
signature := 'f4';
end;
TYP_FLOAT8: begin
signature := 'f8';
end;
TYP_BOOLEAN,
TYP_BYTE: begin
if (flags and STACK) <> 0 then begin
signature := 'i';
end else begin
signature := 'b';
end;
end;
TYP_BYTE2: begin
signature := 'b2';
end;
TYP_BYTE4: begin
signature := 'b4';
end;
TYP_BYTE8: begin
signature := 'b8';
end;
TYP_SHORT: begin
if (flags and STACK) <> 0 then begin
signature := 'i';
end else begin
signature := 's';
end;
end;
TYP_SHORT2: begin
signature := 's2';
end;
TYP_SHORT4: begin
signature := 's4';
end;
TYP_SHORT8: begin
signature := 's8';
end;
TYP_INT: begin
signature := 'i';
end;
TYP_INT2: begin
signature := 'i2';
end;
TYP_INT4: begin
signature := 'i4';
end;
TYP_INT8: begin
signature := 'i8';
end;
TYP_LONG: begin
signature := 'l';
end;
TYP_LONG2: begin
signature := 'l2';
end;
TYP_LONG4: begin
signature := 'l4';
end;
TYP_LONG8: begin
signature := 'l8';
end;
else
signature := '';
end;
result := writeString(signature);
end;
function AssemblerElementWriter.&set(const text: char_Array1d): AssemblerElementWriter;
begin
result := &set(text, 0);
end;
{%endregion}
{%region AssemblerSourcePrintStream }
class function AssemblerSourcePrintStream.getSeparator(state: int): AnsiString;
begin
if state > 0 then begin
result := CoAnsiString.LINE_ENDING;
exit;
end;
result := '';
end;
class procedure AssemblerSourcePrintStream.initialize();
begin
defaultEncoder := Charset.getDefault().newEncoder();
end;
class procedure AssemblerSourcePrintStream.finalize();
begin
defaultEncoder.free();
end;
procedure AssemblerSourcePrintStream.write(const src: char);
begin
fldText := fldText + src;
end;
procedure AssemblerSourcePrintStream.write(const src: AnsiString);
begin
fldText := fldText + src;
end;
function AssemblerSourcePrintStream.spaces(count: int): AnsiString;
var
capacity: int;
buffer: char_Array1d;
begin
buffer := fldSpaces;
if count > system.length(buffer) then begin
capacity := AVTOOService.getBestArrayCapacity(count);
buffer := &Array.newChar1d(capacity);
&Array.fillPrimitives(buffer, 0, capacity, #$20);
fldSpaces := buffer;
end;
result := AnsiString.create(buffer, 0, count);
end;
constructor AssemblerSourcePrintStream.create();
begin
create(nil);
end;
constructor AssemblerSourcePrintStream.create(encoder: CharEncoder);
var
buffer: char_Array1d;
begin
inherited create();
buffer := &Array.newChar1d($ff);
&Array.fillPrimitives(buffer, 0, $ff, #$20);
if encoder = nil then encoder := defaultEncoder;
fldSpaces := buffer;
fldEncoder := encoder;
end;
procedure AssemblerSourcePrintStream.saveToOutputStream(stream: ByteWriter);
begin
saveToOutputStream(stream, nil);
end;
procedure AssemblerSourcePrintStream.saveToOutputStream(stream: ByteWriter; encoder: CharEncoder);
begin
if encoder = nil then encoder := fldEncoder;
encoder.encodeToWriter(stream, fldText.toUTF16());
end;
procedure AssemblerSourcePrintStream.clear();
begin
fldState := 0;
fldMargin := 0;
fldText := '';
end;
procedure AssemblerSourcePrintStream.increaseMargin();
begin
inc(fldMargin);
end;
procedure AssemblerSourcePrintStream.decreaseMargin();
begin
dec(fldMargin);
end;
procedure AssemblerSourcePrintStream.print(const src: AnsiString);
begin
write(src);
fldState := 1;
end;
procedure AssemblerSourcePrintStream.printHeader(const header: AnsiString);
begin
write(getSeparator(fldState));
write(spaces(CoInt.max(fldMargin, 0) shl 2));
write(header);
fldState := 1;
end;
procedure AssemblerSourcePrintStream.printLabel(const &label: AnsiString);
var
str: AnsiString;
begin
str := &label;
if str.length <= 0 then str := #$20#$20#$20#$20#$20'@@';
write(getSeparator(fldState));
write(spaces(CoInt.max(fldMargin, 0) shl 2));
write(str);
write(':');
fldState := str.length + 1;
end;
procedure AssemblerSourcePrintStream.printInstruction(const mnemonic: AnsiString);
var
state: int;
str: AnsiString;
begin
str := mnemonic;
if str.length <= 0 then str := 'nop';
state := fldState;
if (state < 0) or (state > 1) and (state < 12) then begin
write(spaces(CoInt.max(12 - state, 1)));
end else begin
write(getSeparator(state));
write(spaces((CoInt.max(fldMargin, 0) + 3) shl 2));
end;
write(str);
fldState := 1;
end;
procedure AssemblerSourcePrintStream.printInstruction(const mnemonic, operand: AnsiString);
var
state: int;
str: AnsiString;
begin
str := mnemonic;
if str.length <= 0 then str := 'nop';
state := fldState;
if (state < 0) or (state > 1) and (state < 12) then begin
write(spaces(CoInt.max(12 - state, 1)));
end else begin
write(getSeparator(state));
write(spaces((CoInt.max(fldMargin, 0) + 3) shl 2));
end;
write(str);
write(spaces(CoInt.max(12 - str.length, 1)));
write(operand);
fldState := 1;
end;
procedure AssemblerSourcePrintStream.printInstruction(const mnemonic: AnsiString; const operands: AnsiString_Array1d; offset, length: int);
var
state: int;
limit: int;
bounds: int2;
str: AnsiString;
begin
str := mnemonic;
if str.length <= 0 then str := 'nop';
if operands = nil then begin
offset := 0;
length := 0;
end else begin
bounds := VArray.intersectBounds(operands, offset, length);
offset := bounds[0];
length := bounds[1];
end;
state := fldState;
if (state < 0) or (state > 1) and (state < 12) then begin
write(spaces(CoInt.max(12 - state, 1)));
end else begin
write(getSeparator(state));
write(spaces((CoInt.max(fldMargin, 0) + 3) shl 2));
end;
write(str);
if length > 0 then begin
write(spaces(CoInt.max(12 - str.length, 1)));
end;
limit := offset + length - 1;
while offset <= limit do begin
write(operands[offset]);
if offset < limit then write(','#$20);
inc(offset);
end;
fldState := 1;
end;
procedure AssemblerSourcePrintStream.printContinuation(const operands: AnsiString_Array1d; offset, length: int);
var
limit: int;
bounds: int2;
begin
if operands = nil then begin
offset := 0;
length := 0;
end else begin
bounds := VArray.intersectBounds(operands, offset, length);
offset := bounds[0];
length := bounds[1];
end;
write(getSeparator(fldState));
write(spaces((CoInt.max(fldMargin, 0) + 6) shl 2));
limit := offset + length - 1;
while offset <= limit do begin
write(operands[offset]);
if offset < limit then write(','#$20);
inc(offset);
end;
fldState := 1;
end;
procedure AssemblerSourcePrintStream.println();
begin
write(CoAnsiString.LINE_ENDING);
fldState := 0;
end;
procedure AssemblerSourcePrintStream.println(const src: AnsiString);
begin
write(src);
write(CoAnsiString.LINE_ENDING);
fldState := 0;
end;
procedure AssemblerSourcePrintStream.printlnHeader(const header: AnsiString);
begin
write(getSeparator(fldState));
write(spaces(CoInt.max(fldMargin, 0) shl 2));
write(header);
write(CoAnsiString.LINE_ENDING);
fldState := 0;
end;
procedure AssemblerSourcePrintStream.printlnLabel(const &label: AnsiString);
var
str: AnsiString;
begin
str := &label;
if str.length <= 0 then str := #$20#$20#$20#$20#$20'@@';
write(getSeparator(fldState));
write(spaces(CoInt.max(fldMargin, 0) shl 2));
write(str);
write(':');
write(CoAnsiString.LINE_ENDING);
fldState := 0;
end;
procedure AssemblerSourcePrintStream.printlnInstruction(const mnemonic: AnsiString);
var
state: int;
str: AnsiString;
begin
str := mnemonic;
if str.length <= 0 then str := 'nop';
state := fldState;
if (state < 0) or (state > 1) and (state < 12) then begin
write(spaces(CoInt.max(12 - state, 1)));
end else begin
write(getSeparator(state));
write(spaces((CoInt.max(fldMargin, 0) + 3) shl 2));
end;
write(str);
write(CoAnsiString.LINE_ENDING);
fldState := 0;
end;
procedure AssemblerSourcePrintStream.printlnInstruction(const mnemonic, operand: AnsiString);
var
state: int;
str: AnsiString;
begin
str := mnemonic;
if str.length <= 0 then str := 'nop';
state := fldState;
if (state < 0) or (state > 1) and (state < 12) then begin
write(spaces(CoInt.max(12 - state, 1)));
end else begin
write(getSeparator(state));
write(spaces((CoInt.max(fldMargin, 0) + 3) shl 2));
end;
write(str);
write(spaces(CoInt.max(12 - str.length, 1)));
write(operand);
write(CoAnsiString.LINE_ENDING);
fldState := 0;
end;
procedure AssemblerSourcePrintStream.printlnInstruction(const mnemonic: AnsiString; const operands: AnsiString_Array1d; offset, length: int);
var
state: int;
limit: int;
bounds: int2;
str: AnsiString;
begin
str := mnemonic;
if str.length <= 0 then str := 'nop';
if operands = nil then begin
offset := 0;
length := 0;
end else begin
bounds := VArray.intersectBounds(operands, offset, length);
offset := bounds[0];
length := bounds[1];
end;
state := fldState;
if (state < 0) or (state > 1) and (state < 12) then begin
write(spaces(CoInt.max(12 - state, 1)));
end else begin
write(getSeparator(state));
write(spaces((CoInt.max(fldMargin, 0) + 3) shl 2));
end;
write(str);
if length > 0 then begin
write(spaces(CoInt.max(12 - str.length, 1)));
end;
limit := offset + length - 1;
while offset <= limit do begin
write(operands[offset]);
if offset < limit then write(','#$20);
inc(offset);
end;
write(CoAnsiString.LINE_ENDING);
fldState := 0;
end;
procedure AssemblerSourcePrintStream.printlnContinuation(const operands: AnsiString_Array1d; offset, length: int);
var
limit: int;
bounds: int2;
begin
if operands = nil then begin
offset := 0;
length := 0;
end else begin
bounds := VArray.intersectBounds(operands, offset, length);
offset := bounds[0];
length := bounds[1];
end;
write(getSeparator(fldState));
write(spaces((CoInt.max(fldMargin, 0) + 6) shl 2));
limit := offset + length - 1;
while offset <= limit do begin
write(operands[offset]);
if offset < limit then write(','#$20);
inc(offset);
end;
write(CoAnsiString.LINE_ENDING);
fldState := 0;
end;
function AssemblerSourcePrintStream.isEmpty(): boolean;
begin
result := ((fldMargin or fldState) = 0) and (fldText = '');
end;
{%endregion}
{%region AssemblerSourceGenerator }
class procedure AssemblerSourceGenerator.setResourceLocation(table: HashtableOfUnicodeStringToResourceLocation; const name: UnicodeString; newLocation: ResourceLocation);
var
oldLocation: ResourceLocation;
begin
oldLocation := table[name];
if (oldLocation <> nil) and (oldLocation <> newLocation) then oldLocation.free();
table[name] := newLocation;
end;
class procedure AssemblerSourceGenerator.clearResourcesTable(table: HashtableOfUnicodeStringToResourceLocation);
var
index: int;
key: UnicodeString;
value: TObject;
begin
for index := table.length - 1 downto 0 do begin
key := table.keyAt(index);
value := table[key];
table[key] := nil;
value.free();
end;
end;
class procedure AssemblerSourceGenerator.freeResourcesTable(table: HashtableOfUnicodeStringToResourceLocation);
begin
clearResourcesTable(table);
table.free();
end;
class function AssemblerSourceGenerator.isTypeCastAvailable(kindBaseOfSrc, lengthOfSrc, kindBaseOfNew, lengthOfNew: int): boolean;
begin
result := (
(kindBaseOfSrc <> kindBaseOfNew) or (lengthOfSrc <> lengthOfNew)
) and (
(lengthOfSrc > 1) or (lengthOfNew > 1) or
((kindBaseOfSrc <> TYP_BYTE) or (kindBaseOfNew <> TYP_SHORT) and (kindBaseOfNew <> TYP_INT)) and ((kindBaseOfSrc <> TYP_SHORT) or (kindBaseOfNew <> TYP_INT))
);
end;
class function AssemblerSourceGenerator.toRuntimePrimitiveKind(kind: int): int;
const
CLASS_VOID = int(8);
CLASS_BOOLEAN = int(16);
CLASS_CHAR = int(20);
CLASS_BYTE = int(24);
CLASS_SHORT = int(28);
CLASS_INT = int(32);
CLASS_LONG = int(36);
CLASS_FLOAT = int(40);
CLASS_DOUBLE = int(44);
CLASS_REAL = int(48);
begin
case kind of
TYP_VOID:
result := CLASS_VOID;
TYP_BOOLEAN:
result := CLASS_BOOLEAN;
TYP_CHAR:
result := CLASS_CHAR;
TYP_REAL:
result := CLASS_REAL;
TYP_DOUBLE,
TYP_DOUBLE2,
TYP_DOUBLE4,
TYP_DOUBLE8:
result := kind and 3 or CLASS_DOUBLE;
TYP_FLOAT,
TYP_FLOAT2,
TYP_FLOAT4,
TYP_FLOAT8:
result := kind and 3 or CLASS_FLOAT;
TYP_BYTE,
TYP_BYTE2,
TYP_BYTE4,
TYP_BYTE8:
result := kind and 3 or CLASS_BYTE;
TYP_SHORT,
TYP_SHORT2,
TYP_SHORT4,
TYP_SHORT8:
result := kind and 3 or CLASS_SHORT;
TYP_INT,
TYP_INT2,
TYP_INT4,
TYP_INT8:
result := kind and 3 or CLASS_INT;
TYP_LONG,
TYP_LONG2,
TYP_LONG4,
TYP_LONG8:
result := kind and 3 or CLASS_LONG;
else
result := 0;
end;
end;
class function AssemblerSourceGenerator.getNeedRegisterTypeKind(node: Node): int;
var
kind: int;
jump: Node;
operand: TableItem;
synthetic: Callable;
__property: &Property;
begin
if node <> nil then repeat
case node.instruction of
SWAP,
FCT_THROW,
REF_EQ,
REF_NE,
EXP_INSTANCEOF,
REF_IS_NULL,
REF_IS_OBJECT,
NEW_ARRAY_MULTI: begin
result := TYP_REF;
exit;
end;
FCT_BRANCH,
NEW_ARRAY_MONO: begin
result := TYP_INT;
exit;
end;
DUP1,
DUP2,
DUP1X1,
DUP1X2,
TEST_EQZ,
TEST_NEZ,
O_BIT_OR,
O_BIT_AND,
O_BIT_XOR,
O_BIT_NOT,
O_SCAL_NEG,
O_SCAL_MUL,
O_SCAL_DIV,
O_SCAL_DIVU,
O_SCAL_REM,
O_SCAL_REMU,
O_SCAL_ADD,
O_SCAL_SUB,
O_SCAL_EQ,
O_SCAL_NE,
O_SCAL_GT,
O_SCAL_GE,
O_SCAL_LT,
O_SCAL_LE,
O_VECT_LUP,
O_VECT_UUP,
O_VECT_PCK,
O_VECT_NEG,
O_VECT_MUL,
O_VECT_DIV,
O_VECT_ADD,
O_VECT_SUB,
O_VECT_EQ,
O_VECT_NE,
O_VECT_GT,
O_VECT_GE,
O_VECT_LT,
O_VECT_LE,
O_VECT_HMUL,
O_VECT_HMULU,
O_VECT_SADD,
O_VECT_SADDU,
O_VECT_SSUB,
O_VECT_SSUBU: begin
result := (node.operand1 as &Type).kind;
exit;
end;
WRITE_COMPONENT: begin
kind := (node.operand1 as &Type).kind;
if kind = TYP_REF then break;
result := kind;
exit;
end;
CAST_TO: begin
result := (node.operand2 as &Type).kind;
exit;
end;
WRITE_FIELD: begin
result := (node.operand1 as TypedMember).&type.kind;
exit;
end;
WRITE_SPECIAL: begin
__property := node.operand1 as &Property;
if __property.hasIndex() or not Lang.isInstance(__property.writeMember, Field) then break;
result := __property.&type.kind;
exit;
end;
WRITE_PROPERTY: begin
__property := node.operand1 as &Property;
synthetic := __property.writeSynthetic;
if __property.hasIndex() or ((synthetic.serviceIndex and synthetic.virtualIndex) >= 0) or not Lang.isInstance(__property.writeMember, Field) then break;
result := __property.&type.kind;
exit;
end;
NEW_VECTOR: begin
result := (node.operand1 as PrimitiveType).vectorBaseKind;
exit;
end;
READ_FIELD: begin
if (node.operand2 <> nil) or (node.operandC <> nil) then break;
result := TYP_REF;
exit;
end;
READ_SPECIAL: begin
__property := node.operand1 as &Property;
if __property.hasIndex() or not Lang.isInstance(__property.readMember, Field) or (node.operand2 <> nil) or (node.operandC <> nil) then break;
result := TYP_REF;
exit;
end;
READ_PROPERTY: begin
__property := node.operand1 as &Property;
synthetic := __property.readSynthetic;
if
__property.hasIndex() or ((synthetic.serviceIndex and synthetic.virtualIndex) >= 0) or not Lang.isInstance(__property.readMember, Field) or
(node.operand2 <> nil) or (node.operandC <> nil)
then break;
result := TYP_REF;
exit;
end;
READ_COMPONENT: begin
if (node.operand2 = nil) and (node.operandC = nil) then begin
result := TYP_INT;
exit;
end;
result := TYP_REF;
exit;
end;
O_SCAL_SHL,
O_SCAL_SHR,
O_SCAL_SHRU,
O_VECT_SHL,
O_VECT_SHR,
O_VECT_SHRU,
READ_ELEMENT: begin
if (node.operand2 = nil) and (node.operandC = nil) then begin
result := TYP_INT;
exit;
end;
result := (node.operand1 as &Type).kind;
exit;
end;
STORE_STATIC: begin
if (node.operand2 <> nil) or (node.operandC <> nil) then break;
result := (node.operand1 as Field).&type.kind;
exit;
end;
STORE_LOCAL,
DECLARE_WITH,
DECLARE_LOCAL: begin
if node.operandC <> nil then break;
operand := node.operand2;
if operand is &Type then begin
result := &Type(operand).kind;
exit;
end;
result := (node.operand1 as Local).&type.kind;
exit;
end;
FCT_RETURN,
METHOD_LEAVE: begin
result := node.parentCode.parentCallable.&type.kind;
exit;
end;
FCT_JUMP: begin
jump := node.jumpDefault;
if node = jump then break;
node := jump;
end;
else
break;
end;
until false;
result := 0;
end;
class function AssemblerSourceGenerator.getPayLength(const aarray: char_Array1d): int;
var
length: int;
begin
length := &Array.indexOf(#0, aarray, 0, 0);
if length < 0 then length := system.length(aarray);
result := length;
end;
class function AssemblerSourceGenerator.getPayLengthPtr(const aarray): int;
var
length: int;
begin
length := &Array.indexOf(nil, aarray, 0, 0);
if length < 0 then length := system.length(Pointer_Array1d(aarray));
result := length;
end;
class function AssemblerSourceGenerator.toString(const aarray: char_Array1d): AnsiString;
begin
result := AnsiString.create(aarray, 0, getPayLength(aarray));
end;
class function AssemblerSourceGenerator.getTypedItem(itemC: Constant; itemI: TableItem): TypedItem;
begin
if itemC <> nil then begin
result := TypedItem(Lang.cast(itemC, TypedItem));
exit;
end;
if itemI <> nil then begin
result := itemI as TypedItem;
exit;
end;
result := nil;
end;
procedure AssemblerSourceGenerator.findSourcesIn(__library: &Library);
var
oname: UnicodeString;
directoryPath: UnicodeString;
table: HashtableOfUnicodeStringToLibrary;
begin
table := fldSourcesTable;
with __library.fileSystem do begin
directoryPath := __library.directoryPath + ASSEMBLER_SOURCE_PATH;
if isObjectExists(directoryPath) then with findFirst(directoryPath + '/') do try
repeat
oname := name;
if not isObjectNameCaseSensitive() then oname := oname.toLowerCase();
if (oname <> '.') and (oname <> '..') and (oname <> 'code') and (oname <> 'data') and (oname <> 'dbgi') then begin
if directory then begin
findSourcesIn(__library, oname + '/');
end else begin
table[oname] := __library;
end;
end;
until not findNext();
finally
close();
end;
end;
end;
procedure AssemblerSourceGenerator.findSourcesIn(__library: &Library; const __relativePath: UnicodeString);
var
path: UnicodeString;
oname: UnicodeString;
table: HashtableOfUnicodeStringToLibrary;
begin
table := fldSourcesTable;
with __library.fileSystem.findFirst(__library.directoryPath + (ASSEMBLER_SOURCE_PATH + '/') + __relativePath) do try
repeat
oname := name;
if (oname <> '.') and (oname <> '..') then begin
if directory then begin
findSourcesIn(__library, __relativePath + oname + '/');
end else begin
path := __relativePath + oname;
table[path] := __library;
end;
end;
until not findNext();
finally
close();
end;
end;
procedure AssemblerSourceGenerator.constantToFasmString(value: Constant; const operand: char_Array1d);
var
ivalue: int;
bvalue: AnsiString;
begin
if value.isNull() then begin
getAssemblerElementWriter().&set(operand).writeString('null').trim();
exit;
end;
if value.isReflective() then begin
getAssemblerElementWriter().&set(operand).writeString((value.asObject() as RequiredReflectItem).fasmFullName).trim();
exit;
end;
if value.isBoolean() then begin
if value.asBoolean() then begin
bvalue := 'true';
end else begin
bvalue := 'false';
end;
getAssemblerElementWriter().&set(operand).writeString(bvalue).trim();
exit;
end;
case value.&type.kind of
TYP_REAL:
getAssemblerElementWriter().&set(operand).writeChar('[').writeString('cons$e+').writeDecimal(fldRealStorage.indexAcquire(value.asReal()) * 10).writeChar(']').trim();
TYP_DOUBLE:
getAssemblerElementWriter().&set(operand).writeChar('[').writeString('cons$d+').writeOffset(fldDoubleStorage.indexAcquire(value.asDouble()) shl 4).writeChar(']').trim();
TYP_DOUBLE2:
getAssemblerElementWriter().&set(operand).writeChar('[').writeString('cons$d2+').writeOffset(fldDouble2Storage.indexAcquire(value.asDouble2()) shl 4).writeChar(']').trim();
TYP_DOUBLE4:
getAssemblerElementWriter().&set(operand).writeChar('[').writeString('cons$d4+').writeOffset(fldDouble4Storage.indexAcquire(value.asDouble4()) shl 5).writeChar(']').trim();
TYP_DOUBLE8:
getAssemblerElementWriter().&set(operand).writeChar('[').writeString('cons$d8+').writeOffset(fldDouble8Storage.indexAcquire(value.asDouble8()) shl 6).writeChar(']').trim();
TYP_FLOAT:
getAssemblerElementWriter().&set(operand).writeChar('[').writeString('cons$f+').writeOffset(fldFloatStorage.indexAcquire(value.asFloat()) shl 4).writeChar(']').trim();
TYP_FLOAT2:
getAssemblerElementWriter().&set(operand).writeChar('[').writeString('cons$f2+').writeOffset(fldFloat2Storage.indexAcquire(value.asFloat2()) shl 4).writeChar(']').trim();
TYP_FLOAT4:
getAssemblerElementWriter().&set(operand).writeChar('[').writeString('cons$f4+').writeOffset(fldFloat4Storage.indexAcquire(value.asFloat4()) shl 4).writeChar(']').trim();
TYP_FLOAT8:
getAssemblerElementWriter().&set(operand).writeChar('[').writeString('cons$f8+').writeOffset(fldFloat8Storage.indexAcquire(value.asFloat8()) shl 5).writeChar(']').trim();
TYP_BYTE2:
getAssemblerElementWriter().&set(operand).writeChar('[').writeString('cons$b2+').writeOffset(fldByte2Storage.indexAcquire(value.asByte2()) shl 4).writeChar(']').trim();
TYP_BYTE4:
getAssemblerElementWriter().&set(operand).writeChar('[').writeString('cons$b4+').writeOffset(fldByte4Storage.indexAcquire(value.asByte4()) shl 4).writeChar(']').trim();
TYP_BYTE8:
getAssemblerElementWriter().&set(operand).writeChar('[').writeString('cons$b8+').writeOffset(fldByte8Storage.indexAcquire(value.asByte8()) shl 4).writeChar(']').trim();
TYP_SHORT2:
getAssemblerElementWriter().&set(operand).writeChar('[').writeString('cons$s2+').writeOffset(fldShort2Storage.indexAcquire(value.asShort2()) shl 4).writeChar(']').trim();
TYP_SHORT4:
getAssemblerElementWriter().&set(operand).writeChar('[').writeString('cons$s4+').writeOffset(fldShort4Storage.indexAcquire(value.asShort4()) shl 4).writeChar(']').trim();
TYP_SHORT8:
getAssemblerElementWriter().&set(operand).writeChar('[').writeString('cons$s8+').writeOffset(fldShort8Storage.indexAcquire(value.asShort8()) shl 4).writeChar(']').trim();
TYP_INT2:
getAssemblerElementWriter().&set(operand).writeChar('[').writeString('cons$i2+').writeOffset(fldInt2Storage.indexAcquire(value.asInt2()) shl 4).writeChar(']').trim();
TYP_INT4:
getAssemblerElementWriter().&set(operand).writeChar('[').writeString('cons$i4+').writeOffset(fldInt4Storage.indexAcquire(value.asInt4()) shl 4).writeChar(']').trim();
TYP_INT8:
getAssemblerElementWriter().&set(operand).writeChar('[').writeString('cons$i8+').writeOffset(fldInt8Storage.indexAcquire(value.asInt8()) shl 5).writeChar(']').trim();
TYP_LONG:
getAssemblerElementWriter().&set(operand).writeChar('[').writeString('cons$l+').writeOffset(fldLongStorage.indexAcquire(value.asLong()) shl 3).writeChar(']').trim();
TYP_LONG2:
getAssemblerElementWriter().&set(operand).writeChar('[').writeString('cons$l2+').writeOffset(fldLong2Storage.indexAcquire(value.asLong2()) shl 4).writeChar(']').trim();
TYP_LONG4:
getAssemblerElementWriter().&set(operand).writeChar('[').writeString('cons$l4+').writeOffset(fldLong4Storage.indexAcquire(value.asLong4()) shl 5).writeChar(']').trim();
TYP_LONG8:
getAssemblerElementWriter().&set(operand).writeChar('[').writeString('cons$l8+').writeOffset(fldLong8Storage.indexAcquire(value.asLong8()) shl 6).writeChar(']').trim();
else
ivalue := value.asInt();
if ivalue >= 0 then begin
getAssemblerElementWriter().&set(operand).writeInt(ivalue).trim();
exit;
end;
getAssemblerElementWriter().&set(operand).writeChar('-').writeInt(-ivalue).trim();
end;
end;
function AssemblerSourceGenerator.additionalToFasmString(operandC: Constant; operandI: TableItem; const operand: char_Array1d): AnsiString;
begin
if operandC <> nil then begin
constantToFasmString(operandC, operand);
result := '_g';
exit;
end;
if operandI = nil then begin
getAssemblerElementWriter().&set(operand).trim();
result := '';
exit;
end;
if operandI is Local then begin
getAssemblerElementWriter().&set(operand).writeString(operandI.fasmSimpleName).trim();
result := '_l';
exit;
end;
if operandI is Field then begin
getAssemblerElementWriter().&set(operand).writeChar('[').writeString(Field(operandI).fasmFullName).writeChar(']').trim();
result := '_g';
exit;
end;
raise IllegalArgumentException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'illegal-argument'), [ CoAnsiString.create('operandI') ]));
end;
function AssemblerSourceGenerator.additionalToFasmString(operandC: Constant; operandI: TableItem; const operand: char_Array1d; refsLocalTable: HashtableOfAnsiStringToType): AnsiString;
var
name: AnsiString;
begin
if operandC <> nil then begin
constantToFasmString(operandC, operand);
result := '_g';
exit;
end;
if operandI = nil then begin
getAssemblerElementWriter().&set(operand).trim();
result := '';
exit;
end;
if operandI is Local then begin
name := operandI.fasmSimpleName;
if not Local(operandI).&type.isPrimitive() and refsLocalTable.contains(name) then begin
getAssemblerElementWriter().&set(operand).writeChar('$').writeString(name).trim();
end else begin
getAssemblerElementWriter().&set(operand).writeString(name).trim();
end;
result := '_l';
exit;
end;
if operandI is Field then begin
getAssemblerElementWriter().&set(operand).writeChar('[').writeString(Field(operandI).fasmFullName).writeChar(']').trim();
result := '_g';
exit;
end;
raise IllegalArgumentException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'illegal-argument'), [ CoAnsiString.create('operandI') ]));
end;
procedure AssemblerSourceGenerator.findResourcesIn(__library: &Library);
var
directoryPath: UnicodeString;
begin
directoryPath := __library.directoryPath;
with __library.fileSystem do begin
if isObjectExists(directoryPath + TEXT_SOURCE_MAIN_PATH) then begin
findResourcesIn(__library, TEXT_SOURCE_MAIN_PATH + '/');
exit;
end;
if isObjectExists(directoryPath + TEXT_SOURCE_ALTERNATIVE_PATH) then begin
findResourcesIn(__library, TEXT_SOURCE_ALTERNATIVE_PATH + '/');
end;
end;
end;
procedure AssemblerSourceGenerator.findResourcesIn(__library: &Library; const __relativePath: UnicodeString);
var
path: UnicodeString;
oname: UnicodeString;
table: HashtableOfUnicodeStringToResourceLocation;
begin
table := fldResourcesTable;
with __library.fileSystem.findFirst(__library.directoryPath + __relativePath) do try
repeat
oname := name;
if (oname <> '.') and (oname <> '..') then begin
if directory then begin
findResourcesIn(__library, __relativePath + oname + '/');
end else
if not isTypeSourceFileName(oname) then begin
path := __relativePath.substring(__relativePath.indexOf('/')).replaceAll('.', '/') + oname;
setResourceLocation(table, path, ResourceLocation.create(__library, __relativePath + oname));
end;
end;
until not findNext();
finally
close();
end;
end;
procedure AssemblerSourceGenerator.generatePackageData(__pack, __next: Package; output: AssemblerSourcePrintStream);
var
tcount: int;
tindex: int;
tlength: int;
intZero: AnsiString;
longZero: AnsiString;
specialCanonicalName: AnsiString;
operandA: char_Array1d;
operandB: char_Array1d;
operands: AnsiString_Array1d;
__type: &Type;
writer: AssemblerElementWriter;
begin
writer := getAssemblerElementWriter();
tcount := 0;
tlength := __pack.getLength();
operandA := &Array.newChar1d($0100);
operandB := &Array.newChar1d($0020);
intZero := writer.&set(operandB).writeInt(0).get();
longZero := writer.&set(operandB).writeLong(0).get();
operands := &Array.newAnsiString1d(4);
specialCanonicalName := __pack.specialCanonicalName;
if specialCanonicalName = '' then specialCanonicalName := AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.generator.UNIT_NAME, 'comment.system-package');
{ -------------------------------------------------------------------------------------------------------------------------------- }
for tindex := 0 to tlength - 1 do if __pack.readComponent(tindex).isCompilable() then inc(tcount);
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.println();
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.printHeader('; <fold ');
output.print(specialCanonicalName);
output.print(' — ');
output.print(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.generator.UNIT_NAME, 'comment.data.package'));
output.println('>');
output.increaseMargin();
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.printlnInstruction('package', __pack.fasmFullName);
{ -------------------------------------------------------------------------------------------------------------------------------- }
operands[0] := writer.&set(operandA).writeInt(__pack.attributes).get();
operands[1] := writer.&set(operandB).writeInt(fldStringStorage.indexAcquire(__pack.specialSimpleName.toUTF16())).get();
operands[2] := intZero;
operands[3] := intZero;
output.printlnInstruction('dd', operands, 0, 4);
{ -------------------------------------------------------------------------------------------------------------------------------- }
operands[0] := intZero;
operands[1] := intZero;
operands[2] := intZero;
operands[3] := writer.&set(operandA).writeInt(tcount).get();
output.printlnInstruction('dd', operands, 0, 4);
{ -------------------------------------------------------------------------------------------------------------------------------- }
operands[0] := intZero;
operands[1] := intZero;
operands[2] := intZero;
operands[3] := intZero;
output.printlnInstruction('dd', operands, 0, 4);
{ -------------------------------------------------------------------------------------------------------------------------------- }
operands[0] := intZero;
operands[1] := intZero;
operands[2] := intZero;
operands[3] := '-.this+.$type$';
output.printlnInstruction('dd', operands, 0, 4);
{ -------------------------------------------------------------------------------------------------------------------------------- }
operands[0] := intZero;
operands[1] := intZero;
operands[2] := intZero;
operands[3] := intZero;
output.printlnInstruction('dd', operands, 0, 4);
output.printlnInstruction('dd', operands, 0, 4);
{ -------------------------------------------------------------------------------------------------------------------------------- }
operands[0] := longZero;
operands[1] := longZero;
if __next = nil then begin
operands[2] := writer.&set(operandA).writeLong(0).get();
end else begin
operands[2] := writer.&set(operandA).writeString('-.this+').writeString(__next.fasmFullName).get();
end;
operands[3] := longZero;
output.printlnInstruction('dq', operands, 0, 2);
output.printlnInstruction('dq', operands, 2, 2);
{ -------------------------------------------------------------------------------------------------------------------------------- }
operands[0] := longZero;
operands[1] := longZero;
output.printlnInstruction('dq', operands, 0, 2);
{ -------------------------------------------------------------------------------------------------------------------------------- }
operands[0] := intZero;
operands[1] := intZero;
operands[2] := intZero;
operands[3] := '-.this+.$iend$';
output.printlnInstruction('dd', operands, 0, 4);
{ -------------------------------------------------------------------------------------------------------------------------------- }
operands[0] := longZero;
operands[1] := longZero;
output.printlnInstruction('dq', operands, 0, 2);
output.printlnInstruction('dq', operands, 0, 2);
output.printlnInstruction('dq', operands, 0, 2);
output.printlnInstruction('dq', operands, 0, 2);
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.printLabel('.$type$');
for tindex := 0 to tlength - 1 do begin
__type := __pack.readComponent(tindex);
if __type.isCompilable() then begin
writer.&set(operandA).writeString('-.$type$+').writeString(__type.fasmFullName).trim();
output.printlnInstruction('dq', toString(operandA));
end;
end;
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.printlnLabel('.$iend$');
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.decreaseMargin();
output.printlnHeader('; </fold>');
end;
procedure AssemblerSourceGenerator.generatePrimitiveData(__type: PrimitiveType; output: AssemblerSourcePrintStream);
var
intZero: AnsiString;
longZero: AnsiString;
operandA: char_Array1d;
operandB: char_Array1d;
operandC: char_Array1d;
operands: AnsiString_Array1d;
writer: AssemblerElementWriter;
begin
writer := getAssemblerElementWriter();
operandA := &Array.newChar1d($0100);
operandB := &Array.newChar1d($0020);
operandC := &Array.newChar1d($0020);
intZero := writer.&set(operandB).writeInt(0).get();
longZero := writer.&set(operandB).writeLong(0).get();
operands := &Array.newAnsiString1d(4);
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.println();
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.printHeader('; <fold ');
output.print(__type.specialCanonicalName);
output.print(' — ');
output.print(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.generator.UNIT_NAME, 'comment.data.type'));
output.println('>');
output.increaseMargin();
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.printlnInstruction('class', __type.fasmFullName);
{ -------------------------------------------------------------------------------------------------------------------------------- }
operands[0] := writer.&set(operandA).writeInt(__type.attributes).get();
operands[1] := writer.&set(operandB).writeInt(fldStringStorage.indexAcquire(__type.specialSimpleName.toUTF16())).get();
operands[2] := writer.&set(operandC).writeInt(__type.fieldWidth).get();
operands[3] := intZero;
output.printlnInstruction('dd', operands, 0, 4);
{ -------------------------------------------------------------------------------------------------------------------------------- }
operands[0] := intZero;
operands[1] := intZero;
operands[2] := intZero;
operands[3] := intZero;
output.printlnInstruction('dd', operands, 0, 4);
output.printlnInstruction('dd', operands, 0, 4);
output.printlnInstruction('dd', operands, 0, 4);
output.printlnInstruction('dd', operands, 0, 4);
output.printlnInstruction('dd', operands, 0, 4);
{ -------------------------------------------------------------------------------------------------------------------------------- }
operands[0] := longZero;
operands[1] := longZero;
operands[2] := writer.&set(operandA).writeString('-.this+').writeString(__type.parentPackage.fasmFullName).get();
operands[3] := longZero;
output.printlnInstruction('dq', operands, 0, 2);
output.printlnInstruction('dq', operands, 2, 2);
{ -------------------------------------------------------------------------------------------------------------------------------- }
operands[0] := longZero;
operands[1] := longZero;
output.printlnInstruction('dq', operands, 0, 2);
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.printlnInstruction('dq', longZero);
{ -------------------------------------------------------------------------------------------------------------------------------- }
operands[0] := writer.&set(operandA).writeInt(toRuntimePrimitiveKind(__type.kind)).get();
operands[1] := '-.this+.$iend$';
output.printlnInstruction('dd', operands, 0, 2);
{ -------------------------------------------------------------------------------------------------------------------------------- }
operands[0] := longZero;
operands[1] := longZero;
output.printlnInstruction('dq', operands, 0, 2);
output.printlnInstruction('dq', operands, 0, 2);
output.printlnInstruction('dq', operands, 0, 2);
output.printlnInstruction('dq', operands, 0, 2);
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.printlnLabel('.$iend$');
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.decreaseMargin();
output.printlnHeader('; </fold>');
end;
procedure AssemblerSourceGenerator.generateClassData(__type: ClassType; output: AssemblerSourcePrintStream);
type
Field_Array1d = specialize DynamicArray<Field>;
Property_Array1d = specialize DynamicArray<&Property>;
var
hasName: boolean;
isClass: boolean;
isHelper: boolean;
isStruct: boolean;
isService: boolean;
isReflect: boolean;
limit: int;
index: int;
aindex: int;
cindex: int;
sindex: int;
tindex: int;
vindex: int;
ivalue: int;
length: int;
flength: int;
glength: int;
ilength: int;
mlength: int;
nlength: int;
plength: int;
slength: int;
tlength: int;
vlength: int;
tcapacity: int;
i8value: int8;
l8value: long8;
l2value: long2 absolute l8value;
name: AnsiString;
gname: AnsiString;
mnmnc: AnsiString;
intZero: AnsiString;
longZero: AnsiString;
implements: AnsiString;
fasmFullName: AnsiString;
specialCanonicalName: AnsiString;
source: UnicodeString;
operandA: char_Array1d;
operandB: char_Array1d;
operandC: char_Array1d;
operandD: char_Array1d;
fasmNums: char_Array2d;
dmai: int_Array1d;
operands: AnsiString_Array1d;
rfld: Field_Array1d; { нулевые ссылки в конце! }
sfld: Field_Array1d; { нулевые ссылки в конце! }
dfld: Field_Array1d; { нулевые ссылки в конце! }
buffer: Field_Array1d;
globals: Field_Array1d; { нулевые ссылки в конце! }
structs: Field_Array1d; { нулевые ссылки в конце! }
dprp: Property_Array1d; { нулевые ссылки в конце! }
dmth: Callable_Array1d; { нулевые ссылки в конце! }
virt: Callable_Array1d;
srvc: Callable_Array1d;
impl: ClassType_Array1d; { нулевые ссылки в конце! }
serv: ClassType_Array1d;
instances: Field_Array1d; { нулевые ссылки в конце! }
gtype: &Type;
global: Field;
defc: Callable;
__field: Field;
__member: Member;
gvalue: Constant;
component: &Type;
__method: Callable;
prim: PrimitiveType;
__callable: Callable;
__property: &Property;
arguments: ArgumentArray;
astrings: AnsiStringStorage;
astore: ArgumentArrayStorage;
ustrings: UnicodeStringStorage;
curr: ru.malik.elaborarer.avtoo.lang.ClassType;
superclass: ru.malik.elaborarer.avtoo.lang.ClassType;
superservice: ru.malik.elaborarer.avtoo.lang.ClassType;
writer: AssemblerElementWriter;
begin
isReflect := fldReflect;
isService := false;
isStruct := false;
isHelper := __type.isHelper();
if isHelper then begin
isClass := false;
end else begin
if __type.isClass() then begin
isClass := true;
end else begin
isStruct := __type.isStruct();
if isStruct then begin
isClass := true;
end else begin
isService := __type.isService();
isClass := isService and not __type.isAbstract();
end;
end;
end;
tlength := __type.getLength();
superclass := __type.getSuperclassType();
component := nil;
if __type is ArrayType then component := ArrayType(__type).componentType;
{ -------------------------------------------------------------------------------------------------------------------------------- }
rfld := nil;
if isClass then begin
length := 0;
curr := __type;
repeat
for cindex := 0 to curr.getLength() - 1 do begin
__member := curr.readComponent(cindex);
if (__member is Field) and not __member.isStatic() then begin
__field := Field(__member);
name := __member.specialSimpleName;
if not __field.&type.isPrimitive() and (name <> '') then begin
if rfld = nil then begin
rfld := Field_Array1d(&Array.newTObject1d($ff));
end else
if system.length(rfld) = length then begin
buffer := Field_Array1d(&Array.newTObject1d((length shl 1) or 1));
&Array.copyObjects(rfld, 0, buffer, 0, length);
rfld := buffer;
end;
rfld[length] := __field;
inc(length);
end;
end;
end;
curr := curr.getSuperclassType();
until curr = nil;
end;
virt := nil;
if isClass then virt := __type.virtualCallables();
srvc := nil;
if isService then srvc := __type.serviceCallables();
impl := nil;
serv := nil;
begin
slength := __type.getSuperservicesLength();
if isClass then begin
length := 0;
if isService then begin
sindex := -1;
end else begin
sindex := 0;
end;
while sindex < slength do begin
if sindex < 0 then begin
superservice := __type;
end else begin
superservice := __type.getSuperserviceTypeAt(sindex);
end;
if
(superclass = nil) or not superclass.isSuperservice(superservice) or
not superservice.isInterface() and not superclass.hasOverriddingMembersFor(superservice, true) and __type.hasOverriddingMembersFor(superservice, false)
then begin
if impl = nil then impl := ClassType_Array1d(&Array.newTObject1d(slength + 1));
impl[length] := superservice;
inc(length);
end;
inc(sindex);
end;
end;
if not isHelper then begin
length := 0;
for sindex := 0 to slength - 1 do begin
superservice := __type.getSuperserviceTypeAt(sindex);
if serv = nil then serv := ClassType_Array1d(&Array.newTObject1d(slength));
serv[length] := superservice;
inc(length);
end;
end;
end;
sfld := nil;
if isStruct then begin
length := 0;
curr := __type;
repeat
for cindex := 0 to curr.getLength() - 1 do begin
__member := curr.readComponent(cindex);
if (__member is Field) and not __member.isStatic() then begin
__field := Field(__member);
name := __member.specialSimpleName;
if (__field.&type is ReferenceType) and (name <> '') then begin
if sfld = nil then begin
sfld := Field_Array1d(&Array.newTObject1d($ff));
end else
if system.length(sfld) = length then begin
buffer := Field_Array1d(&Array.newTObject1d((length shl 1) or 1));
&Array.copyObjects(sfld, 0, buffer, 0, length);
sfld := buffer;
end;
sfld[length] := __field;
inc(length);
end;
end;
end;
curr := curr.getSuperclassType();
until (curr = nil) or not curr.isStruct();
end;
tcapacity := getBestArrayCapacity(tlength);
dmai := nil;
globals := nil;
if not isStruct then globals := Field_Array1d(&Array.newTObject1d(tcapacity));
structs := nil;
if isStruct then structs := Field_Array1d(&Array.newTObject1d(tcapacity));
instances := nil;
if not isHelper and not isService then instances := Field_Array1d(&Array.newTObject1d(tcapacity));
dfld := nil;
dprp := nil;
dmth := nil;
astore := nil;
try
begin
ilength := 0;
slength := 0;
glength := 0;
flength := 0;
mlength := 0;
plength := 0;
for tindex := 0 to tlength - 1 do begin
__member := __type.readComponent(tindex);
if __member.isStatic() then begin
if (globals <> nil) and (__member is Field) then begin
globals[glength] := Field(__member);
inc(glength);
end;
continue;
end;
if __member is Field then begin
__field := Field(__member);
name := __member.specialSimpleName;
hasName := name <> '';
if (instances <> nil) and (not isStruct or hasName and not __field.&type.isPrimitive()) then begin
instances[ilength] := __field;
inc(ilength);
end;
if (structs <> nil) and hasName then begin
structs[slength] := __field;
inc(slength);
end;
if isReflect and not isStruct then begin
if dfld = nil then dfld := Field_Array1d(&Array.newTObject1d(tlength));
dfld[flength] := __field;
inc(flength);
end;
continue;
end;
if isReflect and not isStruct then begin
if __member is &Property then begin
if dprp = nil then dprp := Property_Array1d(&Array.newTObject1d(tlength));
dprp[plength] := &Property(__member);
inc(plength);
continue;
end;
if __member is Callable then begin
if dmth = nil then begin
dmai := &Array.newInt1d(tlength);
dmth := Callable_Array1d(&Array.newTObject1d(tlength));
astore := ArgumentArrayStorage.create();
end;
__method := Callable(__member);
dmai[mlength] := astore.indexAcquire(__method.arguments);
dmth[mlength] := __method;
inc(mlength);
end;
end;
end;
end;
if isHelper then begin
defc := nil;
end else begin
if isService then begin
curr := superclass;
end else
if not isStruct then begin
curr := __type;
end else begin
curr := getClassType(PACKNAME_LANG + '.' + TYPENAME_STRUCT);
end;
defc := curr.getChildCallable(SPECNAME_INST_INIT, Type_Array1d(nil));
end;
{ -------------------------------------------------------------------------------------------------------------------------------- }
writer := getAssemblerElementWriter();
operandA := &Array.newChar1d($2000);
operandB := &Array.newChar1d($0100);
operandC := &Array.newChar1d($0100);
operandD := &Array.newChar1d($2000);
intZero := writer.&set(operandB).writeInt(0).get();
longZero := writer.&set(operandB).writeLong(0).get();
operands := &Array.newAnsiString1d(8);
source := __type.textSourcePath;
fasmFullName := __type.fasmFullName;
specialCanonicalName := __type.specialCanonicalName;
astrings := fldDebugInfoStrings;
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.println();
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.printHeader('; <fold ');
output.print(specialCanonicalName);
output.print(' — ');
output.print(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.generator.UNIT_NAME, 'comment.data.type'));
output.println('>');
output.increaseMargin();
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.printlnInstruction('class', fasmFullName);
{ -------------------------------------------------------------------------------------------------------------------------------- }
operands[0] := writer.&set(operandA).writeInt(__type.attributes).get();
operands[1] := writer.&set(operandB).writeInt(fldStringStorage.indexAcquire(__type.specialSimpleName.toUTF16())).get();
operands[2] := writer.&set(operandC).writeInt(__type.instanceSize).get();
operands[3] := writer.&set(operandD).writeInt(__type.structSize).get();
output.printlnInstruction('dd', operands, 0, 4);
{ -------------------------------------------------------------------------------------------------------------------------------- }
operands[0] := writer.&set(operandA).writeInt(getPayLengthPtr(rfld)).get();
operands[1] := writer.&set(operandB).writeInt(getPayLengthPtr(virt)).get();
operands[2] := writer.&set(operandC).writeInt(getPayLengthPtr(impl)).get();
operands[3] := writer.&set(operandD).writeInt(getPayLengthPtr(serv)).get();
output.printlnInstruction('dd', operands, 0, 4);
{ -------------------------------------------------------------------------------------------------------------------------------- }
operands[0] := writer.&set(operandA).writeInt(getPayLengthPtr(sfld)).get();
operands[1] := writer.&set(operandB).writeInt(getPayLengthPtr(dfld)).get();
operands[2] := writer.&set(operandC).writeInt(getPayLengthPtr(dmth)).get();
operands[3] := writer.&set(operandD).writeInt(getPayLengthPtr(dprp)).get();
output.printlnInstruction('dd', operands, 0, 4);
{ -------------------------------------------------------------------------------------------------------------------------------- }
&Array.fillStrings(operands, 0, 4, intZero);
if rfld <> nil then operands[0] := '-.this+.$rfld$';
if virt <> nil then operands[1] := '-.this+.$virt$';
if impl <> nil then operands[2] := '-.this+.$impl$';
if serv <> nil then operands[3] := '-.this+.$serv$';
output.printlnInstruction('dd', operands, 0, 4);
{ -------------------------------------------------------------------------------------------------------------------------------- }
&Array.fillStrings(operands, 0, 4, intZero);
if sfld <> nil then operands[0] := '-.this+.$sfld$';
if dfld <> nil then operands[1] := '-.this+.$dfld$';
if dmth <> nil then operands[2] := '-.this+.$dmth$';
if dprp <> nil then operands[3] := '-.this+.$dprp$';
output.printlnInstruction('dd', operands, 0, 4);
{ -------------------------------------------------------------------------------------------------------------------------------- }
&Array.fillStrings(operands, 0, 4, intZero);
if defc <> nil then operands[0] := writer.&set(operandA).writeInt(defc.attributes).get();
output.printlnInstruction('dd', operands, 0, 4);
{ -------------------------------------------------------------------------------------------------------------------------------- }
if isHelper then superclass := __type.getHelperForType();
&Array.fillStrings(operands, 0, 4, longZero);
if superclass <> nil then operands[0] := writer.&set(operandA).writeString('-.this+').writeString(superclass.fasmFullName).get();
if component <> nil then operands[1] := writer.&set(operandB).writeString('-.this+').writeString(component.fasmFullName).get();
operands[2] := writer.&set(operandC).writeString('-.this+').writeString(__type.parentPackage.fasmFullName).get();
if defc <> nil then operands[3] := writer.&set(operandD).writeString('-.this+').writeString(defc.fasmFullName).get();
output.printlnInstruction('dq', operands, 0, 2);
output.printlnInstruction('dq', operands, 2, 2);
{ -------------------------------------------------------------------------------------------------------------------------------- }
operands[0] := longZero;
operands[1] := longZero;
output.printlnInstruction('dq', operands, 0, 2);
{ -------------------------------------------------------------------------------------------------------------------------------- }
writer.&set(operandA).writeString('-.this+dbgi$isrc').writeLabel(fldDebugInfoSources.indexAcquire(source)).trim();
output.printlnInstruction('dq', toString(operandA));
{ -------------------------------------------------------------------------------------------------------------------------------- }
operands[0] := intZero;
operands[1] := '-.this+.$iend$';
output.printlnInstruction('dd', operands, 0, 2);
{ -------------------------------------------------------------------------------------------------------------------------------- }
operands[0] := longZero;
operands[1] := longZero;
output.printlnInstruction('dq', operands, 0, 2);
output.printlnInstruction('dq', operands, 0, 2);
output.printlnInstruction('dq', operands, 0, 2);
output.printlnInstruction('dq', operands, 0, 2);
{ -------------------------------------------------------------------------------------------------------------------------------- }
if rfld <> nil then begin
output.printLabel('.$rfld$');
length := getPayLengthPtr(rfld);
limit := length + (length and 1);
for index := 0 to limit - 1 do begin
if index >= length then begin
output.printlnInstruction('dd', intZero);
end else begin
output.printlnInstruction('dd', rfld[index].fasmFullName);
end;
end;
end;
{ -------------------------------------------------------------------------------------------------------------------------------- }
if virt <> nil then begin
output.printLabel('.$virt$');
for index := 0 to getPayLengthPtr(virt) - 1 do begin
writer.&set(operandA).writeString('-.$virt$+').writeString(virt[index].fasmFullName).trim();
output.printlnInstruction('dq', toString(operandA));
end;
end;
{ -------------------------------------------------------------------------------------------------------------------------------- }
if impl <> nil then begin
output.printLabel('.$impl$');
for index := 0 to getPayLengthPtr(impl) - 1 do begin
implements := impl[index].fasmFullName;
operands[0] := writer.&set(operandA).writeString('-.$impl$+').writeString(fasmFullName).writeString('$$impl$$').writeString(implements).get();
operands[1] := writer.&set(operandB).writeString('-.$impl$+').writeString(implements).get();
output.printlnInstruction('dq', operands, 0, 2);
end;
end;
{ -------------------------------------------------------------------------------------------------------------------------------- }
if serv <> nil then begin
output.printLabel('.$serv$');
for index := 0 to getPayLengthPtr(serv) - 1 do begin
writer.&set(operandA).writeString('-.$serv$+').writeString(serv[index].fasmFullName).trim();
output.printlnInstruction('dq', toString(operandA));
end;
end;
{ -------------------------------------------------------------------------------------------------------------------------------- }
if sfld <> nil then begin
output.printLabel('.$sfld$');
for index := 0 to getPayLengthPtr(sfld) - 1 do begin
__field := sfld[index];
name := __field.specialSimpleName;
astrings.indexAcquire(name);
operands[0] := writer.&set(operandA).writeInt(__field.attributes).get();
operands[1] := name;
operands[2] := __field.&type.fasmFullName;
operands[3] := writer.&set(operandB).writeInt(__field.capacity).get();
operands[4] := __field.fasmFullName;
output.printlnInstruction('dsfld', operands, 0, 5);
end;
end;
{ -------------------------------------------------------------------------------------------------------------------------------- }
if dfld <> nil then begin
output.printLabel('.$dfld$');
for index := 0 to getPayLengthPtr(dfld) - 1 do begin
__field := dfld[index];
name := __field.specialSimpleName;
astrings.indexAcquire(name);
operands[0] := writer.&set(operandA).writeInt(__field.attributes).get();
operands[1] := name;
operands[2] := __field.&type.fasmFullName;
operands[3] := __field.fasmFullName;
output.printlnInstruction('dfild', operands, 0, 4);
end;
end;
{ -------------------------------------------------------------------------------------------------------------------------------- }
if dmth <> nil then begin
output.printLabel('.$dmth$');
for index := 0 to getPayLengthPtr(dmth) - 1 do begin
__method := dmth[index];
name := __method.specialSimpleName;
arguments := __method.arguments;
nlength := name.length;
astrings.indexAcquire(name);
operands[0] := writer.&set(operandA).writeInt(__method.attributes or (arguments.getLength() shl $10)).get();
if (nlength > 1) and (name[1] = '<') and (name[nlength] = '>') then begin
mnmnc := 'dmeths';
operands[1] := writer.&set(operandB).writeString(name, 2, nlength).get();
end else begin
mnmnc := 'dmeth';
operands[1] := name;
end;
operands[2] := __method.&type.fasmFullName;
operands[3] := __method.fasmFullName;
operands[4] := writer.&set(operandC).writeLabel(dmai[index]).get();
output.printlnInstruction(mnmnc, operands, 0, 5);
end;
end;
{ -------------------------------------------------------------------------------------------------------------------------------- }
if dprp <> nil then begin
output.printLabel('.$dprp$');
for index := 0 to getPayLengthPtr(dprp) - 1 do begin
__property := dprp[index];
name := __property.specialSimpleName;
astrings.indexAcquire(name);
operands[0] := writer.&set(operandA).writeInt(__property.attributes).get();
operands[1] := name;
operands[2] := __property.&type.fasmFullName;
&Array.fillStrings(operands, 3, 3, '.$dprp$');
__method := __property.readSynthetic;
if __method <> nil then operands[3] := __method.fasmFullName;
__method := __property.writeSynthetic;
if __method <> nil then operands[4] := __method.fasmFullName;
__method := __property.storedSynthetic;
if __method <> nil then operands[5] := __method.fasmFullName;
output.printlnInstruction('dprop', operands, 0, 6);
end;
end;
{ -------------------------------------------------------------------------------------------------------------------------------- }
if astore <> nil then for aindex := 0 to astore.getLength() - 1 do begin
output.printLabel(writer.&set(operandA).writeLabel(aindex).get());
arguments := astore.readComponent(aindex);
for index := 0 to arguments.getLength() - 1 do begin
writer.&set(operandA).writeChar('-').writeLabel(aindex).writeChar('+').writeString(arguments.readComponent(index).&type.fasmFullName).trim();
output.printlnInstruction('dq', toString(operandA));
end;
end;
finally
astore.free();
end;
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.printlnLabel('.$iend$');
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.decreaseMargin();
output.printlnHeader('; </fold>');
{ -------------------------------------------------------------------------------------------------------------------------------- }
if globals <> nil then begin
fasmNums := [ operandA, operandB, operandC, operandD, &Array.newChar1d($20), &Array.newChar1d($20), &Array.newChar1d($20), &Array.newChar1d($20) ];
ustrings := fldStringStorage;
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.println();
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.printHeader('; <fold ');
output.print(specialCanonicalName);
output.print(' — ');
output.print(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.generator.UNIT_NAME, 'comment.field.static'));
output.println('>');
output.increaseMargin();
{ -------------------------------------------------------------------------------------------------------------------------------- }
for index := 0 to getPayLengthPtr(globals) - 1 do begin
global := globals[index];
gname := global.fasmFullName;
gvalue := global.value;
gtype := global.&type;
if not global.isFinal() or (gvalue = nil) then begin
operands[0] := gname;
operands[1] := gtype.fasmSimpleName;
output.printlnInstruction('glob', operands, 0, 2);
if gvalue = nil then begin
if not(gtype is PrimitiveType) then begin
output.printlnInstruction('dq', 'null');
continue;
end;
prim := PrimitiveType(gtype);
vlength := prim.vectorLength;
case prim.kind of
TYP_BYTE2,
TYP_BYTE4,
TYP_BYTE8: begin
&Array.fillStrings(operands, 0, vlength, writer.&set(operandA).writeByte(0).get());
output.printlnInstruction('db', operands, 0, vlength);
continue;
end;
TYP_SHORT2,
TYP_SHORT4,
TYP_SHORT8: begin
&Array.fillStrings(operands, 0, vlength, writer.&set(operandA).writeShort(0).get());
output.printlnInstruction('dw', operands, 0, vlength);
continue;
end;
TYP_INT2,
TYP_INT4,
TYP_INT8,
TYP_FLOAT,
TYP_FLOAT2,
TYP_FLOAT4,
TYP_FLOAT8: begin
&Array.fillStrings(operands, 0, vlength, writer.&set(operandA).writeInt(0).get());
output.printlnInstruction('dd', operands, 0, vlength);
continue;
end;
TYP_LONG,
TYP_LONG2,
TYP_LONG4,
TYP_LONG8,
TYP_DOUBLE,
TYP_DOUBLE2,
TYP_DOUBLE4,
TYP_DOUBLE8: begin
&Array.fillStrings(operands, 0, vlength, writer.&set(operandA).writeLong(0).get());
output.printlnInstruction('dq', operands, 0, vlength);
continue;
end;
TYP_REAL: begin
&Array.fillStrings(operands, 0, 5, writer.&set(operandA).writeShort(0).get());
output.printlnInstruction('dw', operands, 0, 5);
continue;
end;
else
output.printlnInstruction('dd', intZero);
continue;
end;
end;
prim := gtype as PrimitiveType;
vlength := prim.vectorLength;
case prim.kind of
TYP_BYTE2,
TYP_BYTE4,
TYP_BYTE8: begin
i8value := gvalue.asByte8();
for vindex := 0 to vlength - 1 do begin
operands[vindex] := writer.&set(fasmNums[vindex]).writeByte(i8value[vindex]).get();
end;
output.printlnInstruction('db', operands, 0, vlength);
continue;
end;
TYP_SHORT2,
TYP_SHORT4,
TYP_SHORT8: begin
i8value := gvalue.asShort8();
for vindex := 0 to vlength - 1 do begin
operands[vindex] := writer.&set(fasmNums[vindex]).writeShort(i8value[vindex]).get();
end;
output.printlnInstruction('dw', operands, 0, vlength);
continue;
end;
TYP_INT2,
TYP_INT4,
TYP_INT8: begin
i8value := gvalue.asInt8();
for vindex := 0 to vlength - 1 do begin
operands[vindex] := writer.&set(fasmNums[vindex]).writeInt(i8value[vindex]).get();
end;
output.printlnInstruction('dd', operands, 0, vlength);
continue;
end;
TYP_LONG,
TYP_LONG2,
TYP_LONG4,
TYP_LONG8: begin
l8value := gvalue.asLong8();
for vindex := 0 to vlength - 1 do begin
operands[vindex] := writer.&set(fasmNums[vindex]).writeLong(l8value[vindex]).get();
end;
output.printlnInstruction('dq', operands, 0, vlength);
continue;
end;
TYP_FLOAT,
TYP_FLOAT2,
TYP_FLOAT4,
TYP_FLOAT8: begin
i8value := VCoFloat8.toInt8Bits(gvalue.asFloat8());
for vindex := 0 to vlength - 1 do begin
operands[vindex] := writer.&set(fasmNums[vindex]).writeInt(i8value[vindex]).get();
end;
output.printlnInstruction('dd', operands, 0, vlength);
continue;
end;
TYP_DOUBLE,
TYP_DOUBLE2,
TYP_DOUBLE4,
TYP_DOUBLE8: begin
l8value := VCoDouble8.toLong8Bits(gvalue.asDouble8());
for vindex := 0 to vlength - 1 do begin
operands[vindex] := writer.&set(fasmNums[vindex]).writeLong(l8value[vindex]).get();
end;
output.printlnInstruction('dq', operands, 0, vlength);
continue;
end;
TYP_REAL: begin
l2value := VCoReal.toLong2Bits(gvalue.asReal());
i8value := short8((@l2value)^);
for vindex := 0 to 4 do begin
operands[vindex] := writer.&set(fasmNums[vindex]).writeShort(i8value[vindex]).get();
end;
output.printlnInstruction('dw', operands, 0, 5);
continue;
end;
else
begin
operands[0] := writer.&set(fasmNums[0]).writeInt(gvalue.asInt()).get();
end;
output.printlnInstruction('dd', operands, 0, 1);
continue;
end;
end;
if gvalue.isNull() then begin
operands[0] := gname;
operands[1] := 'null';
output.printlnInstruction('iconst', operands, 0, 2);
continue;
end;
if gvalue.isReflective() then begin
operands[0] := gname;
operands[1] := (gvalue.asObject() as RequiredReflectItem).fasmFullName;
output.printlnInstruction('oconst', operands, 0, 2);
continue;
end;
if gvalue.isString() then begin
operands[0] := gname;
operands[1] := writer.&set(operandA).writeInt(ustrings.indexAcquire((gvalue.asInterface() as Value).asUnicodeString())).get();
output.printlnInstruction('sconst', operands, 0, 2);
continue;
end;
if gvalue.isBoolean() then begin
operands[0] := gname;
if gvalue.asBoolean() then begin
operands[1] := 'true';
end else begin
operands[1] := 'false';
end;
output.printlnInstruction('iconst', operands, 0, 2);
continue;
end;
case gtype.kind of
TYP_REAL:
writer.&set(operandA).writeString(gname).writeString(' at cons$e+').writeDecimal(fldRealStorage.indexAcquire(gvalue.asReal()) * 10).trim();
TYP_DOUBLE:
writer.&set(operandA).writeString(gname).writeString(' at cons$d+').writeOffset(fldDoubleStorage.indexAcquire(gvalue.asDouble()) shl 4).trim();
TYP_DOUBLE2:
writer.&set(operandA).writeString(gname).writeString(' at cons$d2+').writeOffset(fldDouble2Storage.indexAcquire(gvalue.asDouble2()) shl 4).trim();
TYP_DOUBLE4:
writer.&set(operandA).writeString(gname).writeString(' at cons$d4+').writeOffset(fldDouble4Storage.indexAcquire(gvalue.asDouble4()) shl 5).trim();
TYP_DOUBLE8:
writer.&set(operandA).writeString(gname).writeString(' at cons$d8+').writeOffset(fldDouble8Storage.indexAcquire(gvalue.asDouble8()) shl 6).trim();
TYP_FLOAT:
writer.&set(operandA).writeString(gname).writeString(' at cons$f+').writeOffset(fldFloatStorage.indexAcquire(gvalue.asFloat()) shl 4).trim();
TYP_FLOAT2:
writer.&set(operandA).writeString(gname).writeString(' at cons$f2+').writeOffset(fldFloat2Storage.indexAcquire(gvalue.asFloat2()) shl 4).trim();
TYP_FLOAT4:
writer.&set(operandA).writeString(gname).writeString(' at cons$f4+').writeOffset(fldFloat4Storage.indexAcquire(gvalue.asFloat4()) shl 4).trim();
TYP_FLOAT8:
writer.&set(operandA).writeString(gname).writeString(' at cons$f8+').writeOffset(fldFloat8Storage.indexAcquire(gvalue.asFloat8()) shl 5).trim();
TYP_BYTE2:
writer.&set(operandA).writeString(gname).writeString(' at cons$b2+').writeOffset(fldByte2Storage.indexAcquire(gvalue.asByte2()) shl 4).trim();
TYP_BYTE4:
writer.&set(operandA).writeString(gname).writeString(' at cons$b4+').writeOffset(fldByte4Storage.indexAcquire(gvalue.asByte4()) shl 4).trim();
TYP_BYTE8:
writer.&set(operandA).writeString(gname).writeString(' at cons$b8+').writeOffset(fldByte8Storage.indexAcquire(gvalue.asByte8()) shl 4).trim();
TYP_SHORT2:
writer.&set(operandA).writeString(gname).writeString(' at cons$s2+').writeOffset(fldShort2Storage.indexAcquire(gvalue.asShort2()) shl 4).trim();
TYP_SHORT4:
writer.&set(operandA).writeString(gname).writeString(' at cons$s4+').writeOffset(fldShort4Storage.indexAcquire(gvalue.asShort4()) shl 4).trim();
TYP_SHORT8:
writer.&set(operandA).writeString(gname).writeString(' at cons$s8+').writeOffset(fldShort8Storage.indexAcquire(gvalue.asShort8()) shl 4).trim();
TYP_INT2:
writer.&set(operandA).writeString(gname).writeString(' at cons$i2+').writeOffset(fldInt2Storage.indexAcquire(gvalue.asInt2()) shl 4).trim();
TYP_INT4:
writer.&set(operandA).writeString(gname).writeString(' at cons$i4+').writeOffset(fldInt4Storage.indexAcquire(gvalue.asInt4()) shl 4).trim();
TYP_INT8:
writer.&set(operandA).writeString(gname).writeString(' at cons$i8+').writeOffset(fldInt8Storage.indexAcquire(gvalue.asInt8()) shl 5).trim();
TYP_LONG:
writer.&set(operandA).writeString(gname).writeString(' at cons$l+').writeOffset(fldLongStorage.indexAcquire(gvalue.asLong()) shl 3).trim();
TYP_LONG2:
writer.&set(operandA).writeString(gname).writeString(' at cons$l2+').writeOffset(fldLong2Storage.indexAcquire(gvalue.asLong2()) shl 4).trim();
TYP_LONG4:
writer.&set(operandA).writeString(gname).writeString(' at cons$l4+').writeOffset(fldLong4Storage.indexAcquire(gvalue.asLong4()) shl 5).trim();
TYP_LONG8:
writer.&set(operandA).writeString(gname).writeString(' at cons$l8+').writeOffset(fldLong8Storage.indexAcquire(gvalue.asLong8()) shl 6).trim();
else
ivalue := gvalue.asInt();
operands[0] := gname;
if ivalue >= 0 then begin
operands[1] := writer.&set(operandA).writeInt(ivalue).get();
end else begin
operands[1] := writer.&set(operandA).writeChar('-').writeInt(-ivalue).get();
end;
output.printlnInstruction('iconst', operands, 0, 2);
continue;
end;
output.printlnInstruction('label', toString(operandA));
end;
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.printlnInstruction('separator_d');
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.decreaseMargin();
output.printlnHeader('; </fold>');
end;
if instances <> nil then begin
output.println();
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.printHeader('; <fold ');
output.print(specialCanonicalName);
output.print(' — ');
output.print(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.generator.UNIT_NAME, 'comment.field.instance'));
output.println('>');
output.increaseMargin();
{ -------------------------------------------------------------------------------------------------------------------------------- }
for index := 0 to getPayLengthPtr(instances) - 1 do begin
__field := instances[index];
operands[0] := writer.&set(operandA).writeInt(__field.instanceOffset).get();
operands[1] := __field.fasmFullName;
output.printlnInstruction('field', operands, 0, 2);
end;
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.decreaseMargin();
output.printlnHeader('; </fold>');
end;
if structs <> nil then begin
output.println();
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.printHeader('; <fold ');
output.print(specialCanonicalName);
output.print(' — ');
output.print(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.generator.UNIT_NAME, 'comment.field.struct'));
output.println('>');
output.increaseMargin();
{ -------------------------------------------------------------------------------------------------------------------------------- }
for index := 0 to getPayLengthPtr(structs) - 1 do begin
__field := structs[index];
operands[0] := writer.&set(operandA).writeInt(__field.structOffset).get();
operands[1] := writer.&set(operandB).writeString(__field.fasmFullName).writeString('.struct').get();
output.printlnInstruction('field', operands, 0, 2);
end;
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.decreaseMargin();
output.printlnHeader('; </fold>');
end;
if virt <> nil then begin
output.println();
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.printHeader('; <fold ');
output.print(specialCanonicalName);
output.print(' — ');
output.print(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.generator.UNIT_NAME, 'comment.index.virtual'));
output.println('>');
output.increaseMargin();
{ -------------------------------------------------------------------------------------------------------------------------------- }
for index := 0 to system.length(virt) - 1 do begin
__callable := virt[index];
if __callable.parentType = __type then begin
operands[0] := writer.&set(operandA).writeInt(index).get();
operands[1] := __callable.fasmFullName;
output.printlnInstruction('idxvirt', operands, 0, 2);
end;
end;
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.decreaseMargin();
output.printlnHeader('; </fold>');
end;
if srvc <> nil then begin
output.println();
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.printHeader('; <fold ');
output.print(specialCanonicalName);
output.print(' — ');
output.print(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.generator.UNIT_NAME, 'comment.index.service'));
output.println('>');
output.increaseMargin();
{ -------------------------------------------------------------------------------------------------------------------------------- }
for index := 0 to system.length(srvc) - 1 do begin
__callable := srvc[index];
if __callable.parentType = __type then begin
operands[0] := writer.&set(operandA).writeInt(index).get();
operands[1] := __callable.fasmFullName;
output.printlnInstruction('idxserv', operands, 0, 2);
end;
end;
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.decreaseMargin();
output.printlnHeader('; </fold>');
end;
end;
procedure AssemblerSourceGenerator.generateClassCode(__type: ClassType; output: AssemblerSourcePrintStream);
var
isNone: boolean;
index: int;
length: int;
specialCanonicalName: AnsiString;
__member: Member;
__method: Callable;
superclass: ru.malik.elaborarer.avtoo.lang.ClassType;
superservice: ru.malik.elaborarer.avtoo.lang.ClassType;
begin
specialCanonicalName := __type.specialCanonicalName;
begin
output.println();
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.printHeader('; <fold ');
output.print(specialCanonicalName);
output.print(' — ');
output.print(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.generator.UNIT_NAME, 'comment.code.compiled'));
output.println('>');
output.increaseMargin();
{ -------------------------------------------------------------------------------------------------------------------------------- }
isNone := true;
for index := 0 to __type.getLength() - 1 do begin
__member := __type.readComponent(index);
if __member is Callable then begin
__method := Callable(__member);
if not __method.isNative() then begin
if isNone then begin
isNone := false;
end else begin
output.println();
end;
generateCallableCode(__method, output);
end;
end;
end;
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.decreaseMargin();
output.printlnHeader('; </fold>');
end;
if not __type.isHelper() and (__type.isClass() or __type.isStruct() or __type.isService() and not __type.isAbstract()) then begin
output.println();
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.printHeader('; <fold ');
output.print(specialCanonicalName);
output.print(' — ');
output.print(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.generator.UNIT_NAME, 'comment.implementors'));
output.println('>');
output.increaseMargin();
{ -------------------------------------------------------------------------------------------------------------------------------- }
superclass := __type.getSuperclassType();
isNone := true;
length := __type.getSuperservicesLength();
if __type.isService() then begin
index := -1;
end else begin
index := 0;
end;
while index < length do begin
if index < 0 then begin
superservice := __type;
end else begin
superservice := __type.getSuperserviceTypeAt(index);
end;
if
(superclass = nil) or not superclass.isSuperservice(superservice) or
not superservice.isInterface() and not superclass.hasOverriddingMembersFor(superservice, true) and __type.hasOverriddingMembersFor(superservice, false)
then begin
if isNone then begin
isNone := false;
end else begin
output.println();
end;
generateImplementorCode(__type, superservice, output);
end;
inc(index);
end;
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.decreaseMargin();
output.printlnHeader('; </fold>');
end;
end;
procedure AssemblerSourceGenerator.generateCallableCode(__callable: Callable; output: AssemblerSourcePrintStream);
label
break_label0,
break_label2,
break_labelPop,
break_labelPush,
break_labelConj,
continue_label1;
var
isVoid: boolean;
anonymus: boolean;
isInstance: boolean;
isConditionalJump: boolean;
cur: int;
max: int;
min: int;
line: int;
order: int;
flags: int;
index: int;
limit: int;
aindex: int;
alimit: int;
cindex: int;
jindex: int;
jlower: int;
jvalue: int;
sindex: int;
vindex: int;
length: int;
alength: int;
clength: int;
jlength: int;
__label: int;
kindOfNew: int;
kindOfMid: int;
kindOfSrc: int;
lengthOfNew: int;
lengthOfMid: int;
lengthOfSrc: int;
instruction: int;
kindBaseOfNew: int;
kindBaseOfMid: int;
kindBaseOfSrc: int;
kindOfPushType: int;
kindOfResultType: int;
name: AnsiString;
mnmnc: AnsiString;
suffix: AnsiString;
fasmFullName: AnsiString;
textSourcePath: AnsiString;
labels: char_Array2d;
mnemonic: char_Array1d;
operandA: char_Array1d;
operandB: char_Array1d;
operands: AnsiString_Array1d;
target: Node;
__code: Code;
__node: Node;
__next: Node;
__type: &Type;
__prev: &Type;
typeNew: &Type;
typeSrc: &Type;
typeLoc: &Type;
__field: Field;
__local: Local;
__global: Field;
__value: Constant;
argument: Local;
itemC: Constant;
itemI: TableItem;
itemT: TypedItem;
__method: Method;
__source: Source;
jumpIsTrue: Node;
jumpIsFalse: Node;
jumpDefault: Node;
__index: Constant;
__methodc: Callable;
synthetic: Callable;
thisArgument: Local;
reference: TableItem;
__property: &Property;
__member: TypedMember;
arguments: ArgumentArray;
mainArray: UnicodeStringArray;
refsArray: UnicodeStringArray;
mainTable: HashtableOfAnsiStringToType;
refsTable: HashtableOfAnsiStringToType;
lines: ru.malik.elaborarer.avtoo.lang.UnicodeStringArray;
writer: AssemblerElementWriter;
function isNoStackFrameCriteria(): boolean; inline;
begin
{ критерии кусков кода, не создающих стаковый кадр }
if
(
not __callable.isStatic() or (alength > 0)
) or (
(clength <= 2) or
(__code.readComponent(0).instruction <> METHOD_ENTER)
)
then begin
result := false;
exit;
end;
__node := __code.readComponent(1);
instruction := __node.instruction;
result :=
(
(instruction = LOAD_CONST) and not __node.operandC.isString() or
(instruction = LOAD_STATIC)
) and
(__code.readComponent(2).instruction = METHOD_LEAVE)
;
end;
function isFastMethodCriteria(): boolean; inline;
begin
{ критерии кода быстрого метода }
if
(clength > 1) and
(__code.readComponent(0).instruction = METHOD_ENTER) and
(__code.readComponent(1).instruction = METHOD_LEAVE)
then begin
result := true;
exit;
end;
if
(clength > 2) and
(__code.readComponent(0).instruction = METHOD_ENTER)
then begin
__node := __code.readComponent(1);
instruction := __node.instruction;
if
(
(instruction = LOAD_CONST) and not __node.operandC.isString() or
(instruction = READ_FIELD) and ((__node.operand2 <> nil) or (__node.operandC <> nil)) or
(instruction = LOAD_LOCAL)
) and
(__code.readComponent(2).instruction = METHOD_LEAVE)
then begin
result := true;
exit;
end;
end;
if
(clength <= 4) or
(__code.readComponent(0).instruction <> METHOD_ENTER)
then begin
result := false;
exit;
end;
instruction := __code.readComponent(1).instruction;
if
(instruction <> LOAD_LOCAL) and
(instruction <> LOAD_STATIC)
then begin
result := false;
exit;
end;
__node := __code.readComponent(2);
instruction := __node.instruction;
result :=
(
(instruction = LOAD_CONST) and not __node.operandC.isString() or
(instruction = READ_FIELD) and ((__node.operand2 <> nil) or (__node.operandC <> nil)) or
(instruction = LOAD_LOCAL)
) and
(__code.readComponent(3).instruction = WRITE_FIELD) and
(__code.readComponent(4).instruction = METHOD_LEAVE)
;
end;
begin
writer := getAssemblerElementWriter();
mnemonic := &Array.newChar1d($0010);
operandA := &Array.newChar1d($2000);
operandB := &Array.newChar1d($0100);
labels := nil;
operands := &Array.newAnsiString1d(9);
__code := __callable.code;
__source := __callable.source;
textSourcePath := __callable.parentType.textSourcePath.toUTF8();
fasmFullName := __callable.fasmFullName;
arguments := __callable.arguments;
thisArgument := arguments.thisArgument;
isInstance := thisArgument <> nil;
alength := arguments.getLength();
{ -------------------------------------------------------------------------------------------------------------------------------- }
begin
__type := __callable.&type;
isVoid := __type.isVoid();
output.printHeader('if(used ');
output.print(fasmFullName);
output.print(') ; <fold ');
if not isVoid then begin
output.print('returns ');
output.print(__type.specialCanonicalName);
end;
if __callable is Method then begin
__method := Method(__callable);
for index := 0 to __method.getThrowablesLength() - 1 do begin
if index > 0 then begin
output.print(', ');
end else
if isVoid then begin
output.print('throws ');
end else begin
output.print(', throws ');
end;
output.print(__method.getThrowableTypeAt(index).specialCanonicalName);
end;
end;
output.println('>');
output.increaseMargin();
end;
{ -------------------------------------------------------------------------------------------------------------------------------- }
if __code = nil then begin
{ заголовок абстрактного метода }
operands[0] := fasmFullName;
operands[1] := '\';
if not isInstance and (alength <= 0) then begin
output.printlnInstruction('method', operands, 0, 1);
end else begin
output.printlnInstruction('method', operands, 0, 2);
end;
{ -------------------------------------------------------------------------------------------------------------------------------- }
operands[2] := '\';
alimit := alength - 1;
if isInstance then begin
aindex := -1;
end else begin
aindex := 0;
end;
while aindex < alength do begin
if aindex < 0 then begin
argument := thisArgument;
end else begin
argument := arguments.readComponent(aindex);
end;
operands[0] := argument.fasmSimpleName;
operands[1] := argument.&type.fasmSimpleName;
if aindex >= alimit then begin
output.printlnContinuation(operands, 0, 2);
end else begin
output.printlnContinuation(operands, 0, 3);
end;
inc(aindex);
end;
end else begin
clength := __code.getLength();
if not __callable.isInterrupt() then begin
if isNoStackFrameCriteria() then begin
{ заголовок куска кода }
output.printlnInstruction('proc', fasmFullName);
{ -------------------------------------------------------------------------------------------------------------------------------- }
lines := nil;
if Lang.isInstance(__source, TextSource) then begin
lines := TextSource(Lang.cast(__source, TextSource)).lines;
end;
for cindex := 0 to clength - 1 do begin
{ метки }
__node := __code.readComponent(cindex);
__label := __node.debugIndex;
if __label >= 0 then begin
if textSourcePath <> '' then begin
line := __node.location[0];
if line >= 0 then begin
{ строка текстового исходного кода }
writer.&set(operandA).writeDecimal(line + 1).trim();
output.printHeader('; ');
output.print(textSourcePath);
output.print('[');
output.print(toString(operandA));
output.print(']');
if (lines <> nil) and (line < lines.getLength()) then begin
output.print(': ');
output.print(lines.readComponent(line).toString().trim());
end;
output.println();
end;
end;
output.printLabel(writer.&set(operandA).writeLabel('D', __label).get());
end;
__label := __node.labelIndex;
if __label >= 0 then begin
output.printLabel(writer.&set(operandA).writeLabel('L', __label).get());
end;
{ инструкции }
case __node.instruction of
LOAD_CONST: begin
__value := __node.operandC;
constantToFasmString(__value, operandA);
writer.&set(mnemonic).writeString('load').writeSignature(__value.&type, STACK).writeString('_g').trim();
output.printlnInstruction(toString(mnemonic), toString(operandA));
end;
LOAD_STATIC: begin
__global := __node.operand1 as Field;
writer.&set(mnemonic).writeString('load').writeSignature(__global.&type, STACK).writeString('_g').trim();
writer.&set(operandA).writeChar('[').writeString(__global.fasmFullName).writeChar(']').trim();
output.printlnInstruction(toString(mnemonic), toString(operandA));
end;
METHOD_LEAVE: begin
output.printlnInstruction('ret');
output.printlnInstruction('end_proc');
goto break_label0;
end;
end;
end;
end;
if isFastMethodCriteria() then begin
{ заголовок быстрого метода }
operands[0] := fasmFullName;
operands[1] := '\';
if not isInstance and (alength <= 0) then begin
output.printlnInstruction('fast', operands, 0, 1);
end else begin
output.printlnInstruction('fast', operands, 0, 2);
end;
{ -------------------------------------------------------------------------------------------------------------------------------- }
operands[2] := '\';
alimit := alength - 1;
if isInstance then begin
aindex := -1;
end else begin
aindex := 0;
end;
while aindex < alength do begin
if aindex < 0 then begin
argument := thisArgument;
end else begin
argument := arguments.readComponent(aindex);
end;
operands[0] := argument.fasmSimpleName;
operands[1] := argument.&type.fasmSimpleName;
if aindex >= alimit then begin
output.printlnContinuation(operands, 0, 2);
end else begin
output.printlnContinuation(operands, 0, 3);
end;
inc(aindex);
end;
{ -------------------------------------------------------------------------------------------------------------------------------- }
reference := nil;
lines := nil;
if Lang.isInstance(__source, TextSource) then begin
lines := TextSource(Lang.cast(__source, TextSource)).lines;
end;
__node := nil;
if clength > 0 then begin
__node := __code.readComponent(0);
end;
cindex := 0;
repeat
inc(cindex);
if cindex >= clength then begin
__next := nil;
end else begin
__next := __code.readComponent(cindex);
end;
{ метки }
__label := __node.debugIndex;
if __label >= 0 then begin
if textSourcePath <> '' then begin
line := __node.location[0];
if line >= 0 then begin
{ строка текстового исходного кода }
writer.&set(operandA).writeDecimal(line + 1).trim();
output.printHeader('; ');
output.print(textSourcePath);
output.print('[');
output.print(toString(operandA));
output.print(']');
if (lines <> nil) and (line < lines.getLength()) then begin
output.print(': ');
output.print(lines.readComponent(line).toString().trim());
end;
output.println();
end;
end;
output.printLabel(writer.&set(operandA).writeLabel('D', __label).get());
end;
__label := __node.labelIndex;
if __label >= 0 then begin
output.printLabel(writer.&set(operandA).writeLabel('L', __label).get());
end;
{ инструкции }
case __node.instruction of
METHOD_ENTER: begin
output.printlnInstruction('fenter');
end;
LOAD_CONST: begin
__value := __node.operandC;
constantToFasmString(__value, operandA);
if __next.instruction = WRITE_FIELD then begin
flags := STACK or WEAK;
end else begin
flags := STACK;
end;
writer.&set(mnemonic).writeString('load').writeSignature(__value.&type, flags).writeString('_g').trim();
output.printlnInstruction(toString(mnemonic), toString(operandA));
end;
LOAD_LOCAL: begin
if (cindex = 2) and (__next.instruction <> METHOD_LEAVE) then begin
reference := __node.operand1 as Local;
end else begin
__local := __node.operand1 as Local;
typeLoc := __node.operand2 as &Type;
if typeLoc = nil then typeLoc := __local.&type;
if __next.instruction = WRITE_FIELD then begin
flags := STACK or WEAK;
end else begin
flags := STACK;
end;
writer.&set(mnemonic).writeString('load').writeSignature(typeLoc, flags).writeString('_l').trim();
output.printlnInstruction(toString(mnemonic), __local.fasmSimpleName);
end;
end;
LOAD_STATIC: begin
reference := __node.operand1 as Field;
end;
READ_FIELD: begin
__field := __node.operand1 as Field;
itemI := __node.operand2;
itemC := __node.operandC;
__type := __field.&type;
suffix := additionalToFasmString(itemC, itemI, operandA);
if __field.parentType.isStruct() and __type.isPrimitive() then begin
mnmnc := 'frdsf';
end else begin
mnmnc := 'frdif';
end;
if __next.instruction = WRITE_FIELD then begin
flags := WEAK;
end else begin
flags := NORM;
end;
writer.&set(mnemonic).writeString(mnmnc).writeSignature(__type, flags).writeString(suffix).trim();
operands[0] := __field.fasmFullName;
operands[1] := toString(operandA);
output.printlnInstruction(toString(mnemonic), operands, 0, 2);
if (__next.instruction = METHOD_LEAVE) and (itemI is Local) then begin
reference := itemI;
output.printlnInstruction('frelease_o', itemI.fasmSimpleName);
end;
end;
WRITE_FIELD: begin
__field := __node.operand1 as Field;
__type := __field.&type;
suffix := additionalToFasmString(nil, reference, operandA);
if __field.parentType.isStruct() and __type.isPrimitive() then begin
mnmnc := 'fwrsf';
end else begin
mnmnc := 'fwrif';
end;
writer.&set(mnemonic).writeString(mnmnc).writeSignature(__type, WEAK).writeString(suffix).trim();
operands[0] := __field.fasmFullName;
operands[1] := toString(operandA);
output.printlnInstruction(toString(mnemonic), operands, 0, 2);
end;
METHOD_LEAVE: begin
if thisArgument <> nil then begin
aindex := -1;
end else begin
aindex := 0;
end;
while aindex < alength do begin
if aindex < 0 then begin
argument := thisArgument;
end else begin
argument := arguments.readComponent(aindex);
end;
if argument <> reference then case argument.&type.kind of
TYP_INT8,
TYP_LONG4,
TYP_FLOAT8,
TYP_DOUBLE4: begin
output.printlnInstruction('fcltag_y', argument.fasmSimpleName);
end;
TYP_LONG8,
TYP_DOUBLE8: begin
output.printlnInstruction('fcltag_z', argument.fasmSimpleName);
end;
TYP_REF: begin
name := argument.fasmSimpleName;
output.printlnInstruction('frelease', name);
output.printlnInstruction('fcltag_x', name);
end;
end;
inc(aindex);
end;
output.printlnInstruction('fleave');
goto break_label0;
end;
end;
__node := __next;
until false;
end;
end;
{ заголовок нормального метода }
operands[0] := fasmFullName;
operands[1] := '\';
if not isInstance and (alength <= 0) then begin
output.printlnInstruction('method', operands, 0, 1);
end else begin
output.printlnInstruction('method', operands, 0, 2);
end;
{ -------------------------------------------------------------------------------------------------------------------------------- }
operands[2] := '\';
alimit := alength - 1;
if isInstance then begin
aindex := -1;
end else begin
aindex := 0;
end;
while aindex < alength do begin
if aindex < 0 then begin
argument := thisArgument;
end else begin
argument := arguments.readComponent(aindex);
end;
operands[0] := argument.fasmSimpleName;
operands[1] := argument.&type.fasmSimpleName;
if aindex >= alimit then begin
output.printlnContinuation(operands, 0, 2);
end else begin
output.printlnContinuation(operands, 0, 3);
end;
inc(aindex);
end;
{ локальные переменные }
refsTable := HashtableOfAnsiStringToType.create();
try
refsArray := nil;
mainArray := nil;
mainTable := HashtableOfAnsiStringToType.create();
try
refsArray := UnicodeStringArray.create();
mainArray := UnicodeStringArray.create();
with __code.locals do for index := 0 to getLength() - 1 do with readComponent(index) do if not isConstant() then begin
__type := &type;
name := fasmSimpleName;
if not mainTable.contains(name) then begin
mainArray.append(name);
mainTable[name] := __type;
end else
if not refsTable.contains(name) then begin
__prev := mainTable[name];
if __prev.isPrimitive() then begin
if not __type.isPrimitive() then begin
refsArray.append(name);
refsTable[name] := __type;
end else
if __prev.fieldWidth < __type.fieldWidth then begin
mainTable[name] := __type;
end;
end else
if __type.isPrimitive() then begin
refsArray.append(name);
refsTable[name] := __prev;
mainTable[name] := __type;
end;
end else
if __type.isPrimitive() and (mainTable[name].fieldWidth < __type.fieldWidth) then begin
mainTable[name] := __type;
end;
end;
operands[2] := '\';
length := mainArray.getLength();
limit := refsArray.getLength() + length - 1;
for index := 0 to limit do begin
if index < length then begin
name := mainArray.readComponent(index).asAnsiString();
__type := mainTable[name];
operands[0] := name;
end else begin
name := refsArray.readComponent(index - length).asAnsiString();
__type := refsTable[name];
operands[0] := writer.&set(operandA).writeChar('$').writeString(name).get();
end;
operands[1] := __type.fasmSimpleName;
if index <= 0 then begin
if index < limit then begin
output.printlnInstruction('loc', operands, 0, 3);
continue;
end;
output.printlnInstruction('loc', operands, 0, 2);
continue;
end;
if index < limit then begin
output.printlnContinuation(operands, 0, 3);
continue;
end;
output.printlnContinuation(operands, 0, 2);
end;
finally
refsArray.free();
mainArray.free();
mainTable.free();
refsArray := nil;
mainArray := nil;
mainTable := nil;
end;
{ -------------------------------------------------------------------------------------------------------------------------------- }
anonymus := false;
lines := nil;
if Lang.isInstance(__source, TextSource) then begin
lines := TextSource(Lang.cast(__source, TextSource)).lines;
end;
__node := nil;
if clength > 0 then begin
__node := __code.readComponent(0);
end;
cindex := 0;
while cindex < clength do begin
inc(cindex);
if cindex >= clength then begin
__next := nil;
end else begin
__next := __code.readComponent(cindex);
end;
jumpIsTrue := __node.jumpIsTrue;
jumpIsFalse := __node.jumpIsFalse;
isConditionalJump := (jumpIsTrue <> nil) and (jumpIsFalse <> nil);
if isConditionalJump then begin
kindOfResultType := TYP_BOOLEAN;
end else begin
kindOfResultType := getNeedRegisterTypeKind(__next);
end;
{ метки }
__label := __node.debugIndex;
if __label >= 0 then begin
if textSourcePath <> '' then begin
line := __node.location[0];
if line >= 0 then begin
{ строка текстового исходного кода }
writer.&set(operandA).writeDecimal(line + 1).trim();
output.printHeader('; ');
output.print(textSourcePath);
output.print('[');
output.print(toString(operandA));
output.print(']');
if (lines <> nil) and (line < lines.getLength()) then begin
output.print(': ');
output.print(lines.readComponent(line).toString().trim());
end;
output.println();
end;
end;
output.printLabel(writer.&set(operandA).writeLabel('D', __label).get());
end;
__label := __node.labelIndex;
if __label >= 0 then begin
output.printLabel(writer.&set(operandA).writeLabel('L', __label).get());
end;
{ инструкции }
begin
begin
kindOfPushType := TYP_BOOLEAN;
begin
instruction := __node.instruction;
case instruction of
FCT_END,
FCT_BEGIN,
FCT_BOUND: begin
goto continue_label1;
end;
EXP_INSTANCEOF: begin
output.printlnInstruction('instof', (__node.operand1 as ru.malik.elaborarer.avtoo.lang.ClassType).fasmFullName);
end;
FCT_JUMP,
FCT_RETURN,
FCT_BRANCH: begin
if instruction = FCT_BRANCH then begin
jlength := __node.getJumpCasesLength();
if jlength > 0 then begin
if labels = nil then labels := &Array.newChar2d($0008, $0020);
min := __node.getJumpCaseValueAt(0);
max := min;
for jindex := 1 to jlength - 1 do begin
cur := __node.getJumpCaseValueAt(jindex);
if min > cur then min := cur;
if max < cur then max := cur;
end;
jumpDefault := __node.jumpDefault;
if ((long(max) - min + 1) shl 2) + 48 > (long(jlength) + 1) * 10 then begin
operands[0] := writer.&set(operandA).writeLabel(jumpDefault).get();
operands[1] := '\';
output.printlnInstruction('switch_l', operands, 0, 2);
operands[2] := '\';
jindex := 0;
while jindex < jlength do begin
jvalue := __node.getJumpCaseValueAt(jindex);
target := __node.getJumpCaseNodeAt(jindex);
operands[0] := writer.&set(labels[0]).writeInt(jvalue).get();
operands[1] := writer.&set(labels[1]).writeLabel(target).get();
inc(jindex);
if jindex < jlength then begin
output.printlnContinuation(operands, 0, 3);
continue;
end;
output.printlnContinuation(operands, 0, 2);
end;
goto continue_label1;
end;
operands[0] := writer.&set(operandA).writeLabel(jumpDefault).get();
operands[1] := writer.&set(operandB).writeInt(min).get();
operands[2] := '\';
output.printlnInstruction('switch_t', operands, 0, 3);
operands[8] := '\';
jlength := max - min + 1;
jvalue := min;
for jindex := 0 to jlength - 1 do begin
jlower := jindex and 7;
target := __node.getJumpCase(jvalue);
if target = nil then target := jumpDefault;
operands[jlower] := writer.&set(labels[jlower]).writeLabel(target).get();
inc(jlower);
if jvalue = max then begin
output.printlnContinuation(operands, 0, jlower);
end else
if jlower = 8 then begin
output.printlnContinuation(operands, 0, 9);
end;
inc(jvalue);
end;
goto continue_label1;
end;
end;
writer.&set(operandA).writeLabel(__node.jumpDefault).trim();
output.printlnInstruction('jmp', toString(operandA));
goto continue_label1;
end;
FCT_THROW: begin
output.printlnInstruction('throw');
goto continue_label1;
end;
INVOKE_FINALLY: begin
writer.&set(operandA).writeLabel(__node.reference1 as Node).trim();
output.printlnInstruction('invfin', toString(operandA));
goto break_labelPop;
end;
CLINIT_TRY_LOCK: begin
output.printlnInstruction('citrlock', (__node.operand1 as ReflectItem).fasmFullName);
end;
CLINIT_UNLOCK: begin
output.printlnInstruction('ciunlock', (__node.operand1 as ReflectItem).fasmFullName);
goto continue_label1;
end;
FINALLY_ENTER: begin
output.printlnInstruction('finenter');
goto continue_label1;
end;
FINALLY_LEAVE: begin
output.printlnInstruction('finleave');
goto continue_label1;
end;
MONITOR_ENTER: begin
output.printlnInstruction('monenter');
goto continue_label1;
end;
MONITOR_LEAVE: begin
output.printlnInstruction('monleave');
goto continue_label1;
end;
METHOD_ENTER: begin
writer.&set(operandA).writeOffset((__node.reference1 as CoInt).asInt()).trim();
if __callable.isInterrupt() then begin
mnmnc := 'ienter';
end else begin
mnmnc := 'menter';
end;
output.printlnInstruction(mnmnc, toString(operandA));
goto continue_label1;
end;
METHOD_LEAVE: begin
if __callable.isInterrupt() then begin
mnmnc := 'ileave';
end else begin
mnmnc := 'mleave';
end;
output.printlnInstruction(mnmnc);
goto continue_label1;
end;
LOAD_CONST: begin
__value := __node.operandC;
__type := __value.&type;
if __value.isString() then begin
writer.&set(operandA).writeOffset(fldStringStorage.indexAcquire((__value.asInterface() as Value).asUnicodeString())).trim();
output.printlnInstruction('loadstr', toString(operandA));
kindOfPushType := TYP_REF;
goto break_labelPush;
end;
constantToFasmString(__value, operandA);
if __node.weak then begin
flags := STACK or WEAK;
end else begin
flags := STACK;
end;
writer.&set(mnemonic).writeString('load').writeSignature(__type, flags).writeString('_g').trim();
output.printlnInstruction(toString(mnemonic), toString(operandA));
kindOfPushType := __type.kind;
goto break_labelPush;
end;
LOAD_LOCAL: begin
__local := __node.operand1 as Local;
__type := __node.operand2 as &Type;
name := __local.fasmSimpleName;
if __type = nil then __type := __local.&type;
if __node.weak then begin
flags := STACK or WEAK;
end else begin
flags := STACK;
end;
writer.&set(mnemonic).writeString('load').writeSignature(__type, flags).writeString('_l').trim();
if __type.isPrimitive() or not refsTable.contains(name) then begin
operands[0] := name;
end else begin
operands[0] := writer.&set(operandA).writeChar('$').writeString(name).get();
end;
output.printlnInstruction(toString(mnemonic), operands, 0, 1);
kindOfPushType := __type.kind;
end;
LOAD_INTERRUPT: begin
output.printlnInstruction('loadint', (__node.operand1 as ReflectItem).fasmFullName);
kindOfPushType := TYP_LONG;
goto break_labelPush;
end;
LOAD_STATIC: begin
__global := __node.operand1 as Field;
__type := __global.&type;
if __node.weak then begin
flags := STACK or WEAK;
end else begin
flags := STACK;
end;
writer.&set(mnemonic).writeString('load').writeSignature(__type, flags).writeString('_g').trim();
writer.&set(operandA).writeChar('[').writeString(__global.fasmFullName).writeChar(']').trim();
output.printlnInstruction(toString(mnemonic), toString(operandA));
kindOfPushType := __type.kind;
end;
READ_ELEMENT: begin
__type := __node.operand1 as PrimitiveType;
__index := __node.operandC;
if __index = nil then begin
if kindOfResultType <= TYP_VOID then begin
suffix := '_p';
end else begin
suffix := '';
end;
writer.&set(mnemonic).writeString('rdve').writeSignature(__type, NORM).writeString(suffix).trim();
output.printlnInstruction(toString(mnemonic));
goto continue_label1;
end;
writer.&set(mnemonic).writeString('rdve').writeSignature(__type, NORM).writeString('_c').trim();
writer.&set(operandA).writeDecimal(__index.asInt()).trim();
output.printlnInstruction(toString(mnemonic), toString(operandA));
kindOfPushType := PrimitiveType(__type).vectorBaseKind;
goto break_labelPush;
end;
READ_COMPONENT: begin
__type := __node.operand1 as &Type;
itemI := __node.operand2;
itemC := __node.operandC;
itemT := getTypedItem(itemC, itemI);
if itemT = nil then begin
if kindOfResultType <= TYP_VOID then begin
suffix := '_p';
end else begin
suffix := '';
end;
writer.&set(mnemonic).writeString('rdac').writeSignature(__type, NORM).writeString(suffix).trim();
output.printlnInstruction(toString(mnemonic));
goto break_labelConj;
end;
suffix := additionalToFasmString(itemC, itemI, operandA, refsTable);
writer.&set(mnemonic).writeString('rdac').writeSignature(__type, NORM).writeString(suffix).trim();
output.printlnInstruction(toString(mnemonic), toString(operandA));
kindOfPushType := __type.kind;
end;
READ_FIELD: begin
__field := __node.operand1 as Field;
itemI := __node.operand2;
itemC := __node.operandC;
itemT := getTypedItem(itemC, itemI);
__type := __field.&type;
suffix := additionalToFasmString(itemC, itemI, operandA, refsTable);
if __field.parentType.isStruct() and __type.isPrimitive() then begin
mnmnc := 'rdsf';
end else begin
mnmnc := 'rdif';
end;
writer.&set(mnemonic).writeString(mnmnc).writeSignature(__type, NORM).writeString(suffix).trim();
operands[0] := __field.fasmFullName;
operands[1] := toString(operandA);
if itemT = nil then begin
output.printlnInstruction(toString(mnemonic), operands, 0, 1);
end else begin
output.printlnInstruction(toString(mnemonic), operands, 0, 2);
end;
kindOfPushType := __type.kind;
end;
READ_SPECIAL: begin
__property := __node.operand1 as &Property;
itemI := __node.operand2;
itemC := __node.operandC;
itemT := getTypedItem(itemC, itemI);
synthetic := __property.readSynthetic;
if not __property.hasIndex() then begin
__member := __property.readMember;
if Lang.isInstance(__member, Field) then begin
__field := Field(Lang.cast(__member, Field));
__type := __field.&type;
suffix := additionalToFasmString(itemC, itemI, operandA, refsTable);
if __field.parentType.isStruct() and __type.isPrimitive() then begin
mnmnc := 'rdsf';
end else begin
mnmnc := 'rdif';
end;
writer.&set(mnemonic).writeString(mnmnc).writeSignature(__type, NORM).writeString(suffix).trim();
operands[0] := __field.fasmFullName;
operands[1] := toString(operandA);
if itemT = nil then begin
output.printlnInstruction(toString(mnemonic), operands, 0, 1);
end else begin
output.printlnInstruction(toString(mnemonic), operands, 0, 2);
end;
kindOfPushType := __type.kind;
goto break_label2;
end;
if Lang.isInstance(__member, Callable) then begin
if itemT <> nil then begin
suffix := additionalToFasmString(itemC, itemI, operandA, refsTable);
writer.&set(mnemonic).writeString('load').writeSignature(itemT.&type, STACK).writeString(suffix).trim();
output.printlnInstruction(toString(mnemonic), toString(operandA));
output.printlnInstruction('tpushr');
end;
__methodc := Callable(Lang.cast(__member, Callable));
if __methodc.serviceIndex >= 0 then begin
operands[0] := __methodc.parentType.fasmFullName;
operands[1] := writer.&set(operandA).writeString(__methodc.fasmSimpleName).writeString(__methodc.arguments.toFasmString()).get();
output.printlnInstruction('invserv', operands, 0, 2);
end else
if __methodc.virtualIndex >= 0 then begin
output.printlnInstruction('invvirt', __methodc.fasmFullName);
end else begin
output.printlnInstruction('invspec', __methodc.fasmFullName);
end;
kindOfPushType := __methodc.&type.kind;
goto break_label2;
end;
end;
if itemT <> nil then begin
suffix := additionalToFasmString(itemC, itemI, operandA, refsTable);
writer.&set(mnemonic).writeString('load').writeSignature(itemT.&type, STACK).writeString(suffix).trim();
output.printlnInstruction(toString(mnemonic), toString(operandA));
output.printlnInstruction('tpushr');
end;
output.printlnInstruction('invspec', synthetic.fasmFullName);
kindOfPushType := synthetic.&type.kind;
end;
READ_PROPERTY: begin
__property := __node.operand1 as &Property;
itemI := __node.operand2;
itemC := __node.operandC;
itemT := getTypedItem(itemC, itemI);
synthetic := __property.readSynthetic;
sindex := synthetic.serviceIndex;
vindex := synthetic.virtualIndex;
if not __property.hasIndex() and ((sindex and vindex) < 0) then begin
__member := __property.readMember;
if Lang.isInstance(__member, Field) then begin
__field := Field(Lang.cast(__member, Field));
__type := __field.&type;
suffix := additionalToFasmString(itemC, itemI, operandA, refsTable);
if __field.parentType.isStruct() and __type.isPrimitive() then begin
mnmnc := 'rdsf';
end else begin
mnmnc := 'rdif';
end;
writer.&set(mnemonic).writeString(mnmnc).writeSignature(__type, NORM).writeString(suffix).trim();
operands[0] := __field.fasmFullName;
operands[1] := toString(operandA);
if itemT = nil then begin
output.printlnInstruction(toString(mnemonic), operands, 0, 1);
end else begin
output.printlnInstruction(toString(mnemonic), operands, 0, 2);
end;
kindOfPushType := __type.kind;
goto break_label2;
end;
if Lang.isInstance(__member, Callable) then begin
if itemT <> nil then begin
suffix := additionalToFasmString(itemC, itemI, operandA, refsTable);
writer.&set(mnemonic).writeString('load').writeSignature(itemT.&type, STACK).writeString(suffix).trim();
output.printlnInstruction(toString(mnemonic), toString(operandA));
output.printlnInstruction('tpushr');
end;
__methodc := Callable(Lang.cast(__member, Callable));
if __methodc.serviceIndex >= 0 then begin
operands[0] := __methodc.parentType.fasmFullName;
operands[1] := writer.&set(operandA).writeString(__methodc.fasmSimpleName).writeString(__methodc.arguments.toFasmString()).get();
output.printlnInstruction('invserv', operands, 0, 2);
end else
if __methodc.virtualIndex >= 0 then begin
output.printlnInstruction('invvirt', __methodc.fasmFullName);
end else begin
output.printlnInstruction('invspec', __methodc.fasmFullName);
end;
kindOfPushType := __methodc.&type.kind;
goto break_label2;
end;
end;
if itemT <> nil then begin
suffix := additionalToFasmString(itemC, itemI, operandA, refsTable);
writer.&set(mnemonic).writeString('load').writeSignature(itemT.&type, STACK).writeString(suffix).trim();
output.printlnInstruction(toString(mnemonic), toString(operandA));
output.printlnInstruction('tpushr');
end;
if sindex >= 0 then begin
operands[0] := synthetic.parentType.fasmFullName;
operands[1] := writer.&set(operandA).writeString(synthetic.fasmSimpleName).writeString(synthetic.arguments.toFasmString()).get();
output.printlnInstruction('invserv', operands, 0, 2);
end else
if vindex >= 0 then begin
output.printlnInstruction('invvirt', synthetic.fasmFullName);
end else begin
output.printlnInstruction('invspec', synthetic.fasmFullName);
end;
kindOfPushType := synthetic.&type.kind;
end;
SWAP: begin
writer.&set(mnemonic).writeString('tswap').writeSignature(__node.operand1 as &Type, STACK).writeString('_p').trim();
output.printlnInstruction(toString(mnemonic));
goto continue_label1;
end;
DUP1: begin
if kindOfResultType <= TYP_VOID then begin
suffix := '_p';
end else begin
suffix := '';
end;
writer.&set(mnemonic).writeString('tdup1').writeSignature(__node.operand1 as &Type, STACK).writeString(suffix).trim();
output.printlnInstruction(toString(mnemonic));
goto break_labelConj;
end;
DUP1X1: begin
if kindOfResultType <= TYP_VOID then begin
suffix := '_p';
end else begin
suffix := '';
end;
writer.&set(mnemonic).writeString('tdup1x1').writeSignature(__node.operand1 as &Type, STACK).writeString(suffix).trim();
output.printlnInstruction(toString(mnemonic));
goto break_labelConj;
end;
DUP1X2: begin
if kindOfResultType <= TYP_VOID then begin
suffix := '_p';
end else begin
suffix := '';
end;
writer.&set(mnemonic).writeString('tdup1x2').writeSignature(__node.operand1 as &Type, STACK).writeString(suffix).trim();
output.printlnInstruction(toString(mnemonic));
goto break_labelConj;
end;
DUP2: begin
if kindOfResultType <= TYP_VOID then begin
suffix := '_p';
end else begin
suffix := '';
end;
writer.&set(mnemonic).writeString('tdup2').writeSignature(__node.operand1 as &Type, STACK).writeString(suffix).trim();
output.printlnInstruction(toString(mnemonic));
goto break_labelConj;
end;
INVOKE_STATIC: begin
__methodc := __node.operand1 as Callable;
__type := __methodc.&type;
output.printlnInstruction('invstat', __methodc.fasmFullName);
if __type.isVoid() then goto break_labelPop;
if __node.weak then begin
writer.&set(mnemonic).writeString('release').writeSignature(__type, STACK).trim();
output.printlnInstruction(toString(mnemonic));
goto break_labelPop;
end;
kindOfPushType := __type.kind;
end;
INVOKE_SPECIAL: begin
__methodc := __node.operand1 as Callable;
__type := __methodc.&type;
output.printlnInstruction('invspec', __methodc.fasmFullName);
if __type.isVoid() then goto break_labelPop;
if __node.weak then begin
writer.&set(mnemonic).writeString('release').writeSignature(__type, STACK).trim();
output.printlnInstruction(toString(mnemonic));
goto break_labelPop;
end;
kindOfPushType := __type.kind;
end;
INVOKE_VIRTUAL: begin
__methodc := __node.operand1 as Callable;
__type := __methodc.&type;
if __methodc.virtualIndex >= 0 then begin
output.printlnInstruction('invvirt', __methodc.fasmFullName);
end else begin
output.printlnInstruction('invspec', __methodc.fasmFullName);
end;
if __type.isVoid() then goto break_labelPop;
if __node.weak then begin
writer.&set(mnemonic).writeString('release').writeSignature(__type, STACK).trim();
output.printlnInstruction(toString(mnemonic));
goto break_labelPop;
end;
kindOfPushType := __type.kind;
end;
INVOKE_SERVICE: begin
__methodc := __node.operand1 as Callable;
__type := __methodc.&type;
if __methodc.serviceIndex >= 0 then begin
operands[0] := __methodc.parentType.fasmFullName;
operands[1] := writer.&set(operandA).writeString(__methodc.fasmSimpleName).writeString(__methodc.arguments.toFasmString()).get();
output.printlnInstruction('invserv', operands, 0, 2);
end else
if __methodc.virtualIndex >= 0 then begin
output.printlnInstruction('invvirt', __methodc.fasmFullName);
end else begin
output.printlnInstruction('invspec', __methodc.fasmFullName);
end;
if __type.isVoid() then goto break_labelPop;
if __node.weak then begin
writer.&set(mnemonic).writeString('release').writeSignature(__type, STACK).trim();
output.printlnInstruction(toString(mnemonic));
goto break_labelPop;
end;
kindOfPushType := __type.kind;
end;
NEW_VECTOR: begin
if kindOfResultType <= TYP_VOID then begin
suffix := '_p';
end else begin
suffix := '';
end;
writer.&set(mnemonic).writeString('newv').writeSignature(__node.operand1 as PrimitiveType, NORM).writeString(suffix).trim();
output.printlnInstruction(toString(mnemonic));
goto continue_label1;
end;
NEW_ARRAY: begin
operands[0] := (__node.operand1 as ArrayType).fasmFullName;
operands[1] := writer.&set(operandA).writeInt(__node.operandC.asInt()).get();
output.printlnInstruction('newa_c', operands, 0, 2);
kindOfPushType := TYP_REF;
goto break_labelPush;
end;
NEW_ARRAY_MONO: begin
output.printlnInstruction('newa', (__node.operand1 as ArrayType).fasmFullName);
kindOfPushType := TYP_REF;
goto break_labelPush;
end;
NEW_ARRAY_MULTI: begin
output.printlnInstruction('newam', (__node.operand1 as ArrayType).fasmFullName);
kindOfPushType := TYP_REF;
goto break_labelPush;
end;
NEW_INSTANCE: begin
output.printlnInstruction('newi', (__node.operand1 as ru.malik.elaborarer.avtoo.lang.ClassType).fasmFullName);
kindOfPushType := TYP_REF;
goto break_labelPush;
end;
CAST_TO: begin
typeNew := __node.operand1 as &Type;
typeSrc := __node.operand2 as &Type;
if not typeNew.isPrimitive() then begin
output.printlnInstruction('castrto', typeNew.fasmFullName);
kindOfPushType := TYP_REF;
goto break_labelPush;
end;
with typeNew as PrimitiveType do begin
kindOfNew := kind;
lengthOfNew := vectorLength;
kindBaseOfNew := vectorBaseKind;
end;
with typeSrc as PrimitiveType do begin
kindOfSrc := kind;
lengthOfSrc := vectorLength;
kindBaseOfSrc := vectorBaseKind;
end;
if kindOfSrc = TYP_CHAR then begin
kindOfSrc := TYP_INT;
lengthOfSrc := 1;
kindBaseOfSrc := TYP_INT;
end;
if kindOfNew = TYP_CHAR then begin
case kindBaseOfSrc of
TYP_CHAR: ;
TYP_BYTE,
TYP_SHORT,
TYP_INT: begin
if lengthOfSrc > 1 then begin
writer.&set(mnemonic).writeString('cast').writeSignature(kindOfSrc, STACK).writeString('to').writeSignature(kindBaseOfSrc, NORM).trim();
output.printlnInstruction(toString(mnemonic));
end;
output.printlnInstruction('castitoc');
end;
else
if lengthOfSrc > 1 then begin
writer.&set(mnemonic).writeString('cast').writeSignature(kindOfSrc, STACK).writeString('to').writeSignature(kindBaseOfSrc, NORM).trim();
output.printlnInstruction(toString(mnemonic));
end;
writer.&set(mnemonic).writeString('cast').writeSignature(kindBaseOfSrc, STACK).writeString('toi').trim();
output.printlnInstruction(toString(mnemonic));
output.printlnInstruction('castitoc');
end;
end else
if lengthOfNew < lengthOfSrc then begin
kindOfMid := kindBaseOfSrc or kindOfNew and 3;
lengthOfMid := lengthOfNew;
kindBaseOfMid := kindBaseOfSrc;
{ понижение длины вектора }
begin
writer.&set(mnemonic).writeString('cast').writeSignature(kindOfSrc, STACK).writeString('to').writeSignature(kindOfMid, NORM).trim();
output.printlnInstruction(toString(mnemonic));
end;
{ изменение типа элементов вектора }
if isTypeCastAvailable(kindBaseOfMid, lengthOfMid, kindBaseOfNew, lengthOfNew) then begin
writer.&set(mnemonic).writeString('cast').writeSignature(kindOfMid, STACK).writeString('to').writeSignature(kindOfNew, NORM).trim();
output.printlnInstruction(toString(mnemonic));
end;
end else
if lengthOfNew > lengthOfSrc then begin
kindOfMid := kindBaseOfNew or kindOfSrc and 3;
lengthOfMid := lengthOfSrc;
kindBaseOfMid := kindBaseOfNew;
{ изменение типа элементов вектора }
if isTypeCastAvailable(kindBaseOfSrc, lengthOfSrc, kindBaseOfMid, lengthOfMid) then begin
writer.&set(mnemonic).writeString('cast').writeSignature(kindOfSrc, STACK).writeString('to').writeSignature(kindOfMid, NORM).trim();
output.printlnInstruction(toString(mnemonic));
end;
{ повышение длины вектора }
begin
writer.&set(mnemonic).writeString('cast').writeSignature(kindOfMid, STACK).writeString('to').writeSignature(kindOfNew, NORM).trim();
output.printlnInstruction(toString(mnemonic));
end;
end else begin
{ изменение типа элементов вектора }
if isTypeCastAvailable(kindBaseOfSrc, lengthOfSrc, kindBaseOfNew, lengthOfNew) then begin
writer.&set(mnemonic).writeString('cast').writeSignature(kindOfSrc, STACK).writeString('to').writeSignature(kindOfNew, NORM).trim();
output.printlnInstruction(toString(mnemonic));
end;
end;
kindOfPushType := kindOfNew;
goto break_labelPush;
end;
INC_LOCAL: begin
__local := __node.operand1 as Local;
__type := __node.operand2 as &Type;
if __type = nil then __type := __local.&type;
writer.&set(mnemonic).writeString('inc').writeSignature(__type, NORM).writeString('_l').trim();
output.printlnInstruction(toString(mnemonic), __local.fasmSimpleName);
goto continue_label1;
end;
DEC_LOCAL: begin
__local := __node.operand1 as Local;
__type := __node.operand2 as &Type;
if __type = nil then __type := __local.&type;
writer.&set(mnemonic).writeString('dec').writeSignature(__type, NORM).writeString('_l').trim();
output.printlnInstruction(toString(mnemonic), __local.fasmSimpleName);
goto continue_label1;
end;
INC_PRED_LOAD_LOCAL: begin
__local := __node.operand1 as Local;
__type := __node.operand2 as &Type;
if __type = nil then __type := __local.&type;
writer.&set(mnemonic).writeString('incload').writeSignature(__type, NORM).writeString('_l').trim();
output.printlnInstruction(toString(mnemonic), __local.fasmSimpleName);
kindOfPushType := __type.kind;
goto break_labelPush;
end;
DEC_PRED_LOAD_LOCAL: begin
__local := __node.operand1 as Local;
__type := __node.operand2 as &Type;
if __type = nil then __type := __local.&type;
writer.&set(mnemonic).writeString('decload').writeSignature(__type, NORM).writeString('_l').trim();
output.printlnInstruction(toString(mnemonic), __local.fasmSimpleName);
kindOfPushType := __type.kind;
goto break_labelPush;
end;
INC_POST_LOAD_LOCAL: begin
__local := __node.operand1 as Local;
__type := __node.operand2 as &Type;
if __type = nil then __type := __local.&type;
writer.&set(mnemonic).writeString('loadinc').writeSignature(__type, NORM).writeString('_l').trim();
output.printlnInstruction(toString(mnemonic), __local.fasmSimpleName);
kindOfPushType := __type.kind;
goto break_labelPush;
end;
DEC_POST_LOAD_LOCAL: begin
__local := __node.operand1 as Local;
__type := __node.operand2 as &Type;
if __type = nil then __type := __local.&type;
writer.&set(mnemonic).writeString('loaddec').writeSignature(__type, NORM).writeString('_l').trim();
output.printlnInstruction(toString(mnemonic), __local.fasmSimpleName);
kindOfPushType := __type.kind;
goto break_labelPush;
end;
REF_EQ: begin
itemI := __node.operand1;
itemC := __node.operandC;
itemT := getTypedItem(itemC, itemI);
suffix := additionalToFasmString(itemC, itemI, operandB, refsTable);
if isConditionalJump then begin
order := __node.order + 1;
if jumpIsFalse.order = order then begin
if __node.weak then begin
mnmnc := 'jweq';
end else begin
mnmnc := 'jreq';
end;
writer.&set(mnemonic).writeString(mnmnc).writeString(suffix).trim();
operands[0] := writer.&set(operandA).writeLabel(jumpIsTrue).get();
operands[1] := toString(operandB);
if itemT = nil then begin
output.printlnInstruction(toString(mnemonic), operands, 0, 1);
goto continue_label1;
end;
output.printlnInstruction(toString(mnemonic), operands, 0, 2);
goto continue_label1;
end;
begin
if __node.weak then begin
mnmnc := 'jwne';
end else begin
mnmnc := 'jrne';
end;
writer.&set(mnemonic).writeString(mnmnc).writeString(suffix).trim();
operands[0] := writer.&set(operandA).writeLabel(jumpIsFalse).get();
operands[1] := toString(operandB);
if itemT = nil then begin
output.printlnInstruction(toString(mnemonic), operands, 0, 1);
end else begin
output.printlnInstruction(toString(mnemonic), operands, 0, 2);
end;
end;
if jumpIsTrue.order <> order then begin
writer.&set(operandA).writeLabel(jumpIsTrue).trim();
output.printlnInstruction('jmp', toString(operandA));
end;
goto continue_label1;
end;
if itemT = nil then begin
if kindOfResultType <= TYP_VOID then begin
mnmnc := 'setreq_p';
end else begin
mnmnc := 'setreq';
end;
output.printlnInstruction(mnmnc);
goto continue_label1;
end;
if __node.weak then begin
mnmnc := 'setweq';
end else begin
mnmnc := 'setreq';
end;
writer.&set(mnemonic).writeString(mnmnc).writeString(suffix).trim();
output.printlnInstruction(toString(mnemonic), toString(operandB));
goto break_labelPush;
end;
REF_NE: begin
itemI := __node.operand1;
itemC := __node.operandC;
itemT := getTypedItem(itemC, itemI);
suffix := additionalToFasmString(itemC, itemI, operandB, refsTable);
if isConditionalJump then begin
order := __node.order + 1;
if jumpIsFalse.order = order then begin
if __node.weak then begin
mnmnc := 'jwne';
end else begin
mnmnc := 'jrne';
end;
writer.&set(mnemonic).writeString(mnmnc).writeString(suffix).trim();
operands[0] := writer.&set(operandA).writeLabel(jumpIsTrue).get();
operands[1] := toString(operandB);
if itemT = nil then begin
output.printlnInstruction(toString(mnemonic), operands, 0, 1);
goto continue_label1;
end;
output.printlnInstruction(toString(mnemonic), operands, 0, 2);
goto continue_label1;
end;
begin
if __node.weak then begin
mnmnc := 'jweq';
end else begin
mnmnc := 'jreq';
end;
writer.&set(mnemonic).writeString(mnmnc).writeString(suffix).trim();
operands[0] := writer.&set(operandA).writeLabel(jumpIsFalse).get();
operands[1] := toString(operandB);
if itemT = nil then begin
output.printlnInstruction(toString(mnemonic), operands, 0, 1);
end else begin
output.printlnInstruction(toString(mnemonic), operands, 0, 2);
end;
end;
if jumpIsTrue.order <> order then begin
writer.&set(operandA).writeLabel(jumpIsTrue).trim();
output.printlnInstruction('jmp', toString(operandA));
end;
goto continue_label1;
end;
if itemT = nil then begin
if kindOfResultType <= TYP_VOID then begin
mnmnc := 'setrne_p';
end else begin
mnmnc := 'setrne';
end;
output.printlnInstruction(mnmnc);
goto continue_label1;
end;
if __node.weak then begin
mnmnc := 'setwne';
end else begin
mnmnc := 'setrne';
end;
writer.&set(mnemonic).writeString(mnmnc).writeString(suffix).trim();
output.printlnInstruction(toString(mnemonic), toString(operandB));
goto break_labelPush;
end;
REF_IS_NULL: begin
if isConditionalJump then begin
order := __node.order + 1;
if jumpIsFalse.order = order then begin
writer.&set(operandA).writeLabel(jumpIsTrue).trim();
if __node.weak then begin
mnmnc := 'jwisnull';
end else begin
mnmnc := 'jrisnull';
end;
output.printlnInstruction(mnmnc, toString(operandA));
goto continue_label1;
end;
begin
writer.&set(operandA).writeLabel(jumpIsFalse).trim();
if __node.weak then begin
mnmnc := 'jwisobj';
end else begin
mnmnc := 'jrisobj';
end;
output.printlnInstruction(mnmnc, toString(operandA));
end;
if jumpIsTrue.order <> order then begin
writer.&set(operandA).writeLabel(jumpIsTrue).trim();
output.printlnInstruction('jmp', toString(operandA));
end;
goto continue_label1;
end;
if __node.weak then begin
mnmnc := 'setwisnull';
end else begin
mnmnc := 'setrisnull';
end;
output.printlnInstruction(mnmnc);
goto break_labelPush;
end;
REF_IS_OBJECT: begin
if isConditionalJump then begin
order := __node.order + 1;
if jumpIsFalse.order = order then begin
writer.&set(operandA).writeLabel(jumpIsTrue).trim();
if __node.weak then begin
mnmnc := 'jwisobj';
end else begin
mnmnc := 'jrisobj';
end;
output.printlnInstruction(mnmnc, toString(operandA));
goto continue_label1;
end;
begin
writer.&set(operandA).writeLabel(jumpIsFalse).trim();
if __node.weak then begin
mnmnc := 'jwisnull';
end else begin
mnmnc := 'jrisnull';
end;
output.printlnInstruction(mnmnc, toString(operandA));
end;
if jumpIsTrue.order <> order then begin
writer.&set(operandA).writeLabel(jumpIsTrue).trim();
output.printlnInstruction('jmp', toString(operandA));
end;
goto continue_label1;
end;
if __node.weak then begin
mnmnc := 'setwisobj';
end else begin
mnmnc := 'setrisobj';
end;
output.printlnInstruction(mnmnc);
goto break_labelPush;
end;
TEST_EQZ: begin
__type := __node.operand1 as PrimitiveType;
itemI := __node.operand2;
itemC := __node.operandC;
itemT := getTypedItem(itemC, ItemI);
suffix := additionalToFasmString(itemC, itemI, operandB, refsTable);
if isConditionalJump then begin
order := __node.order + 1;
if jumpIsFalse.order = order then begin
writer.&set(mnemonic).writeString('jteq').writeSignature(__type, STACK).writeString(suffix).trim();
operands[0] := writer.&set(operandA).writeLabel(jumpIsTrue).get();
operands[1] := toString(operandB);
if itemT = nil then begin
output.printlnInstruction(toString(mnemonic), operands, 0, 1);
goto continue_label1;
end;
output.printlnInstruction(toString(mnemonic), operands, 0, 2);
goto continue_label1;
end;
begin
writer.&set(mnemonic).writeString('jtne').writeSignature(__type, STACK).writeString(suffix).trim();
operands[0] := writer.&set(operandA).writeLabel(jumpIsFalse).get();
operands[1] := toString(operandB);
if itemT = nil then begin
output.printlnInstruction(toString(mnemonic), operands, 0, 1);
end else begin
output.printlnInstruction(toString(mnemonic), operands, 0, 2);
end;
end;
if jumpIsTrue.order <> order then begin
writer.&set(operandA).writeLabel(jumpIsTrue).trim();
output.printlnInstruction('jmp', toString(operandA));
end;
goto continue_label1;
end;
if itemT = nil then begin
if kindOfResultType <= TYP_VOID then begin
suffix := '_p';
end else begin
suffix := '';
end;
writer.&set(mnemonic).writeString('setteq').writeSignature(__type, STACK).writeString(suffix).trim();
output.printlnInstruction(toString(mnemonic));
goto continue_label1;
end;
writer.&set(mnemonic).writeString('setteq').writeSignature(__type, STACK).writeString(suffix).trim();
output.printlnInstruction(toString(mnemonic), toString(operandB));
goto break_labelPush;
end;
TEST_NEZ: begin
__type := __node.operand1 as PrimitiveType;
itemI := __node.operand2;
itemC := __node.operandC;
itemT := getTypedItem(itemC, ItemI);
suffix := additionalToFasmString(itemC, itemI, operandB, refsTable);
if isConditionalJump then begin
order := __node.order + 1;
if jumpIsFalse.order = order then begin
writer.&set(mnemonic).writeString('jtne').writeSignature(__type, STACK).writeString(suffix).trim();
operands[0] := writer.&set(operandA).writeLabel(jumpIsTrue).get();
operands[1] := toString(operandB);
if itemT = nil then begin
output.printlnInstruction(toString(mnemonic), operands, 0, 1);
goto continue_label1;
end;
output.printlnInstruction(toString(mnemonic), operands, 0, 2);
goto continue_label1;
end;
begin
writer.&set(mnemonic).writeString('jteq').writeSignature(__type, STACK).writeString(suffix).trim();
operands[0] := writer.&set(operandA).writeLabel(jumpIsFalse).get();
operands[1] := toString(operandB);
if itemT = nil then begin
output.printlnInstruction(toString(mnemonic), operands, 0, 1);
end else begin
output.printlnInstruction(toString(mnemonic), operands, 0, 2);
end;
end;
if jumpIsTrue.order <> order then begin
writer.&set(operandA).writeLabel(jumpIsTrue).trim();
output.printlnInstruction('jmp', toString(operandA));
end;
goto continue_label1;
end;
if itemT = nil then begin
if kindOfResultType <= TYP_VOID then begin
suffix := '_p';
end else begin
suffix := '';
end;
writer.&set(mnemonic).writeString('settne').writeSignature(__type, STACK).writeString(suffix).trim();
output.printlnInstruction(toString(mnemonic));
goto continue_label1;
end;
writer.&set(mnemonic).writeString('settne').writeSignature(__type, STACK).writeString(suffix).trim();
output.printlnInstruction(toString(mnemonic), toString(operandB));
goto break_labelPush;
end;
O_BIT_NOT: begin
__type := __node.operand1 as PrimitiveType;
writer.&set(mnemonic).writeString('bnot').writeSignature(__type, STACK).trim();
output.printlnInstruction(toString(mnemonic));
kindOfPushType := __type.kind;
end;
O_BIT_AND: begin
__type := __node.operand1 as PrimitiveType;
itemI := __node.operand2;
itemC := __node.operandC;
itemT := getTypedItem(itemC, itemI);
suffix := additionalToFasmString(itemC, itemI, operandB, refsTable);
if isConditionalJump then begin
order := __node.order + 1;
if jumpIsFalse.order = order then begin
writer.&set(mnemonic).writeString('jtne').writeSignature(__type, STACK).writeString(suffix).trim();
operands[0] := writer.&set(operandA).writeLabel(jumpIsTrue).get();
operands[1] := toString(operandB);
if itemT = nil then begin
output.printlnInstruction(toString(mnemonic), operands, 0, 1);
goto continue_label1;
end;
output.printlnInstruction(toString(mnemonic), operands, 0, 2);
goto continue_label1;
end;
begin
writer.&set(mnemonic).writeString('jteq').writeSignature(__type, STACK).writeString(suffix).trim();
operands[0] := writer.&set(operandA).writeLabel(jumpIsFalse).get();
operands[1] := toString(operandB);
if itemT = nil then begin
output.printlnInstruction(toString(mnemonic), operands, 0, 1);
end else begin
output.printlnInstruction(toString(mnemonic), operands, 0, 2);
end;
end;
if jumpIsTrue.order <> order then begin
writer.&set(operandA).writeLabel(jumpIsTrue).trim();
output.printlnInstruction('jmp', toString(operandA));
end;
goto continue_label1;
end;
if itemT = nil then begin
if kindOfResultType <= TYP_VOID then begin
suffix := '_p';
end else begin
suffix := '';
end;
writer.&set(mnemonic).writeString('band').writeSignature(__type, STACK).writeString(suffix).trim();
output.printlnInstruction(toString(mnemonic));
goto continue_label1;
end;
writer.&set(mnemonic).writeString('band').writeSignature(__type, STACK).writeString(suffix).trim();
output.printlnInstruction(toString(mnemonic), toString(operandB));
kindOfPushType := __type.kind;
goto break_labelPush;
end;
O_BIT_OR: begin
__type := __node.operand1 as PrimitiveType;
itemI := __node.operand2;
itemC := __node.operandC;
itemT := getTypedItem(itemC, itemI);
suffix := additionalToFasmString(itemC, itemI, operandA, refsTable);
if itemT = nil then begin
if kindOfResultType <= TYP_VOID then begin
suffix := '_p';
end else begin
suffix := '';
end;
writer.&set(mnemonic).writeString('bor').writeSignature(__type, STACK).writeString(suffix).trim();
output.printlnInstruction(toString(mnemonic));
goto break_labelConj;
end;
writer.&set(mnemonic).writeString('bor').writeSignature(__type, STACK).writeString(suffix).trim();
output.printlnInstruction(toString(mnemonic), toString(operandA));
kindOfPushType := __type.kind;
end;
O_BIT_XOR: begin
__type := __node.operand1 as PrimitiveType;
itemI := __node.operand2;
itemC := __node.operandC;
itemT := getTypedItem(itemC, itemI);
suffix := additionalToFasmString(itemC, itemI, operandA, refsTable);
if itemT = nil then begin
if kindOfResultType <= TYP_VOID then begin
suffix := '_p';
end else begin
suffix := '';
end;
writer.&set(mnemonic).writeString('bxor').writeSignature(__type, STACK).writeString(suffix).trim();
output.printlnInstruction(toString(mnemonic));
goto break_labelConj;
end;
writer.&set(mnemonic).writeString('bxor').writeSignature(__type, STACK).writeString(suffix).trim();
output.printlnInstruction(toString(mnemonic), toString(operandA));
kindOfPushType := __type.kind;
end;
O_SCAL_NEG: begin
__type := __node.operand1 as PrimitiveType;
writer.&set(mnemonic).writeString('sneg').writeSignature(__type, STACK).trim();
output.printlnInstruction(toString(mnemonic));
kindOfPushType := __type.kind;
goto break_labelPush;
end;
O_SCAL_MUL: begin
__type := __node.operand1 as PrimitiveType;
itemI := __node.operand2;
itemC := __node.operandC;
itemT := getTypedItem(itemC, itemI);
suffix := additionalToFasmString(itemC, itemI, operandA, refsTable);
if itemT = nil then begin
if kindOfResultType <= TYP_VOID then begin
suffix := '_p';
end else begin
suffix := '';
end;
writer.&set(mnemonic).writeString('smul').writeSignature(__type, STACK).writeString(suffix).trim();
output.printlnInstruction(toString(mnemonic));
goto continue_label1;
end;
writer.&set(mnemonic).writeString('smul').writeSignature(__type, STACK).writeString(suffix).trim();
output.printlnInstruction(toString(mnemonic), toString(operandA));
kindOfPushType := __type.kind;
goto break_labelPush;
end;
O_SCAL_DIV: begin
__type := __node.operand1 as PrimitiveType;
itemI := __node.operand2;
itemC := __node.operandC;
itemT := getTypedItem(itemC, itemI);
suffix := additionalToFasmString(itemC, itemI, operandA, refsTable);
if itemT = nil then begin
if kindOfResultType <= TYP_VOID then begin
suffix := '_p';
end else begin
suffix := '';
end;
writer.&set(mnemonic).writeString('sdiv').writeSignature(__type, STACK).writeString(suffix).trim();
output.printlnInstruction(toString(mnemonic));
goto continue_label1;
end;
writer.&set(mnemonic).writeString('sdiv').writeSignature(__type, STACK).writeString(suffix).trim();
output.printlnInstruction(toString(mnemonic), toString(operandA));
kindOfPushType := __type.kind;
goto break_labelPush;
end;
O_SCAL_DIVU: begin
__type := __node.operand1 as PrimitiveType;
itemI := __node.operand2;
itemC := __node.operandC;
itemT := getTypedItem(itemC, itemI);
suffix := additionalToFasmString(itemC, itemI, operandA, refsTable);
if itemT = nil then begin
if kindOfResultType <= TYP_VOID then begin
suffix := '_p';
end else begin
suffix := '';
end;
writer.&set(mnemonic).writeString('sdivu').writeSignature(__type, STACK).writeString(suffix).trim();
output.printlnInstruction(toString(mnemonic));
goto continue_label1;
end;
writer.&set(mnemonic).writeString('sdivu').writeSignature(__type, STACK).writeString(suffix).trim();
output.printlnInstruction(toString(mnemonic), toString(operandA));
kindOfPushType := __type.kind;
goto break_labelPush;
end;
O_SCAL_REM: begin
__type := __node.operand1 as PrimitiveType;
itemI := __node.operand2;
itemC := __node.operandC;
itemT := getTypedItem(itemC, itemI);
suffix := additionalToFasmString(itemC, itemI, operandA, refsTable);
if itemT = nil then begin
if kindOfResultType <= TYP_VOID then begin
suffix := '_p';
end else begin
suffix := '';
end;
writer.&set(mnemonic).writeString('srem').writeSignature(__type, STACK).writeString(suffix).trim();
output.printlnInstruction(toString(mnemonic));
goto continue_label1;
end;
writer.&set(mnemonic).writeString('srem').writeSignature(__type, STACK).writeString(suffix).trim();
output.printlnInstruction(toString(mnemonic), toString(operandA));
kindOfPushType := __type.kind;
goto break_labelPush;
end;
O_SCAL_REMU: begin
__type := __node.operand1 as PrimitiveType;
itemI := __node.operand2;
itemC := __node.operandC;
itemT := getTypedItem(itemC, itemI);
suffix := additionalToFasmString(itemC, itemI, operandA, refsTable);
if itemT = nil then begin
if kindOfResultType <= TYP_VOID then begin
suffix := '_p';
end else begin
suffix := '';
end;
writer.&set(mnemonic).writeString('sremu').writeSignature(__type, STACK).writeString(suffix).trim();
output.printlnInstruction(toString(mnemonic));
goto continue_label1;
end;
writer.&set(mnemonic).writeString('sremu').writeSignature(__type, STACK).writeString(suffix).trim();
output.printlnInstruction(toString(mnemonic), toString(operandA));
kindOfPushType := __type.kind;
goto break_labelPush;
end;
O_SCAL_ADD: begin
__type := __node.operand1 as PrimitiveType;
itemI := __node.operand2;
itemC := __node.operandC;
itemT := getTypedItem(itemC, itemI);
suffix := additionalToFasmString(itemC, itemI, operandA, refsTable);
if itemT = nil then begin
if kindOfResultType <= TYP_VOID then begin
suffix := '_p';
end else begin
suffix := '';
end;
writer.&set(mnemonic).writeString('sadd').writeSignature(__type, STACK).writeString(suffix).trim();
output.printlnInstruction(toString(mnemonic));
goto continue_label1;
end;
writer.&set(mnemonic).writeString('sadd').writeSignature(__type, STACK).writeString(suffix).trim();
output.printlnInstruction(toString(mnemonic), toString(operandA));
kindOfPushType := __type.kind;
goto break_labelPush;
end;
O_SCAL_SUB: begin
__type := __node.operand1 as PrimitiveType;
itemI := __node.operand2;
itemC := __node.operandC;
itemT := getTypedItem(itemC, itemI);
suffix := additionalToFasmString(itemC, itemI, operandA, refsTable);
if itemT = nil then begin
if kindOfResultType <= TYP_VOID then begin
suffix := '_p';
end else begin
suffix := '';
end;
writer.&set(mnemonic).writeString('ssub').writeSignature(__type, STACK).writeString(suffix).trim();
output.printlnInstruction(toString(mnemonic));
goto continue_label1;
end;
writer.&set(mnemonic).writeString('ssub').writeSignature(__type, STACK).writeString(suffix).trim();
output.printlnInstruction(toString(mnemonic), toString(operandA));
kindOfPushType := __type.kind;
goto break_labelPush;
end;
O_SCAL_SHR: begin
__type := __node.operand1 as PrimitiveType;
itemI := __node.operand2;
itemC := __node.operandC;
itemT := getTypedItem(itemC, itemI);
suffix := additionalToFasmString(itemC, itemI, operandA, refsTable);
if itemT = nil then begin
if kindOfResultType <= TYP_VOID then begin
suffix := '_p';
end else begin
suffix := '';
end;
writer.&set(mnemonic).writeString('sshr').writeSignature(__type, STACK).writeString(suffix).trim();
output.printlnInstruction(toString(mnemonic));
goto continue_label1;
end;
writer.&set(mnemonic).writeString('sshr').writeSignature(__type, STACK).writeString(suffix).trim();
output.printlnInstruction(toString(mnemonic), toString(operandA));
kindOfPushType := __type.kind;
goto break_labelPush;
end;
O_SCAL_SHRU: begin
__type := __node.operand1 as PrimitiveType;
itemI := __node.operand2;
itemC := __node.operandC;
itemT := getTypedItem(itemC, itemI);
suffix := additionalToFasmString(itemC, itemI, operandA, refsTable);
if itemT = nil then begin
if kindOfResultType <= TYP_VOID then begin
suffix := '_p';
end else begin
suffix := '';
end;
writer.&set(mnemonic).writeString('sshru').writeSignature(__type, STACK).writeString(suffix).trim();
output.printlnInstruction(toString(mnemonic));
goto continue_label1;
end;
writer.&set(mnemonic).writeString('sshru').writeSignature(__type, STACK).writeString(suffix).trim();
output.printlnInstruction(toString(mnemonic), toString(operandA));
kindOfPushType := __type.kind;
goto break_labelPush;
end;
O_SCAL_SHL: begin
__type := __node.operand1 as PrimitiveType;
itemI := __node.operand2;
itemC := __node.operandC;
itemT := getTypedItem(itemC, itemI);
suffix := additionalToFasmString(itemC, itemI, operandA, refsTable);
if itemT = nil then begin
if kindOfResultType <= TYP_VOID then begin
suffix := '_p';
end else begin
suffix := '';
end;
writer.&set(mnemonic).writeString('sshl').writeSignature(__type, STACK).writeString(suffix).trim();
output.printlnInstruction(toString(mnemonic));
goto continue_label1;
end;
writer.&set(mnemonic).writeString('sshl').writeSignature(__type, STACK).writeString(suffix).trim();
output.printlnInstruction(toString(mnemonic), toString(operandA));
kindOfPushType := __type.kind;
goto break_labelPush;
end;
O_SCAL_EQ: begin
__type := __node.operand1 as PrimitiveType;
itemI := __node.operand2;
itemC := __node.operandC;
itemT := getTypedItem(itemC, ItemI);
suffix := additionalToFasmString(itemC, itemI, operandB, refsTable);
if isConditionalJump then begin
order := __node.order + 1;
if jumpIsFalse.order = order then begin
writer.&set(mnemonic).writeString('jseq').writeSignature(__type, STACK).writeString(suffix).trim();
operands[0] := writer.&set(operandA).writeLabel(jumpIsTrue).get();
operands[1] := toString(operandB);
if itemT = nil then begin
output.printlnInstruction(toString(mnemonic), operands, 0, 1);
goto continue_label1;
end;
output.printlnInstruction(toString(mnemonic), operands, 0, 2);
goto continue_label1;
end;
begin
writer.&set(mnemonic).writeString('jsne').writeSignature(__type, STACK).writeString(suffix).trim();
operands[0] := writer.&set(operandA).writeLabel(jumpIsFalse).get();
operands[1] := toString(operandB);
if itemT = nil then begin
output.printlnInstruction(toString(mnemonic), operands, 0, 1);
end else begin
output.printlnInstruction(toString(mnemonic), operands, 0, 2);
end;
end;
if jumpIsTrue.order <> order then begin
writer.&set(operandA).writeLabel(jumpIsTrue).trim();
output.printlnInstruction('jmp', toString(operandA));
end;
goto continue_label1;
end;
if itemT = nil then begin
if kindOfResultType <= TYP_VOID then begin
suffix := '_p';
end else begin
suffix := '';
end;
writer.&set(mnemonic).writeString('setseq').writeSignature(__type, STACK).writeString(suffix).trim();
output.printlnInstruction(toString(mnemonic));
goto continue_label1;
end;
writer.&set(mnemonic).writeString('setseq').writeSignature(__type, STACK).writeString(suffix).trim();
output.printlnInstruction(toString(mnemonic), toString(operandB));
goto break_labelPush;
end;
O_SCAL_NE: begin
__type := __node.operand1 as PrimitiveType;
itemI := __node.operand2;
itemC := __node.operandC;
itemT := getTypedItem(itemC, ItemI);
suffix := additionalToFasmString(itemC, itemI, operandB, refsTable);
if isConditionalJump then begin
order := __node.order + 1;
if jumpIsFalse.order = order then begin
writer.&set(mnemonic).writeString('jsne').writeSignature(__type, STACK).writeString(suffix).trim();
operands[0] := writer.&set(operandA).writeLabel(jumpIsTrue).get();
operands[1] := toString(operandB);
if itemT = nil then begin
output.printlnInstruction(toString(mnemonic), operands, 0, 1);
goto continue_label1;
end;
output.printlnInstruction(toString(mnemonic), operands, 0, 2);
goto continue_label1;
end;
begin
writer.&set(mnemonic).writeString('jseq').writeSignature(__type, STACK).writeString(suffix).trim();
operands[0] := writer.&set(operandA).writeLabel(jumpIsFalse).get();
operands[1] := toString(operandB);
if itemT = nil then begin
output.printlnInstruction(toString(mnemonic), operands, 0, 1);
end else begin
output.printlnInstruction(toString(mnemonic), operands, 0, 2);
end;
end;
if jumpIsTrue.order <> order then begin
writer.&set(operandA).writeLabel(jumpIsTrue).trim();
output.printlnInstruction('jmp', toString(operandA));
end;
goto continue_label1;
end;
if itemT = nil then begin
if kindOfResultType <= TYP_VOID then begin
suffix := '_p';
end else begin
suffix := '';
end;
writer.&set(mnemonic).writeString('setsne').writeSignature(__type, STACK).writeString(suffix).trim();
output.printlnInstruction(toString(mnemonic));
goto continue_label1;
end;
writer.&set(mnemonic).writeString('setsne').writeSignature(__type, STACK).writeString(suffix).trim();
output.printlnInstruction(toString(mnemonic), toString(operandB));
goto break_labelPush;
end;
O_SCAL_GT: begin
__type := __node.operand1 as PrimitiveType;
itemI := __node.operand2;
itemC := __node.operandC;
itemT := getTypedItem(itemC, ItemI);
suffix := additionalToFasmString(itemC, itemI, operandB, refsTable);
if isConditionalJump then begin
order := __node.order + 1;
if jumpIsFalse.order = order then begin
if __type.isFloating() then begin
mnmnc := 'jsgtl';
end else begin
mnmnc := 'jsgt';
end;
writer.&set(mnemonic).writeString(mnmnc).writeSignature(__type, STACK).writeString(suffix).trim();
operands[0] := writer.&set(operandA).writeLabel(jumpIsTrue).get();
operands[1] := toString(operandB);
if itemT = nil then begin
output.printlnInstruction(toString(mnemonic), operands, 0, 1);
goto continue_label1;
end;
output.printlnInstruction(toString(mnemonic), operands, 0, 2);
goto continue_label1;
end;
begin
if __type.isFloating() then begin
mnmnc := 'jslel';
end else begin
mnmnc := 'jsle';
end;
writer.&set(mnemonic).writeString(mnmnc).writeSignature(__type, STACK).writeString(suffix).trim();
operands[0] := writer.&set(operandA).writeLabel(jumpIsFalse).get();
operands[1] := toString(operandB);
if itemT = nil then begin
output.printlnInstruction(toString(mnemonic), operands, 0, 1);
end else begin
output.printlnInstruction(toString(mnemonic), operands, 0, 2);
end;
end;
if jumpIsTrue.order <> order then begin
writer.&set(operandA).writeLabel(jumpIsTrue).trim();
output.printlnInstruction('jmp', toString(operandA));
end;
goto continue_label1;
end;
if itemT = nil then begin
if kindOfResultType <= TYP_VOID then begin
suffix := '_p';
end else begin
suffix := '';
end;
writer.&set(mnemonic).writeString('setsgt').writeSignature(__type, STACK).writeString(suffix).trim();
output.printlnInstruction(toString(mnemonic));
goto continue_label1;
end;
writer.&set(mnemonic).writeString('setsgt').writeSignature(__type, STACK).writeString(suffix).trim();
output.printlnInstruction(toString(mnemonic), toString(operandB));
goto break_labelPush;
end;
O_SCAL_GE: begin
__type := __node.operand1 as PrimitiveType;
itemI := __node.operand2;
itemC := __node.operandC;
itemT := getTypedItem(itemC, ItemI);
suffix := additionalToFasmString(itemC, itemI, operandB, refsTable);
if isConditionalJump then begin
order := __node.order + 1;
if jumpIsFalse.order = order then begin
if __type.isFloating() then begin
mnmnc := 'jsgel';
end else begin
mnmnc := 'jsge';
end;
writer.&set(mnemonic).writeString(mnmnc).writeSignature(__type, STACK).writeString(suffix).trim();
operands[0] := writer.&set(operandA).writeLabel(jumpIsTrue).get();
operands[1] := toString(operandB);
if itemT = nil then begin
output.printlnInstruction(toString(mnemonic), operands, 0, 1);
goto continue_label1;
end;
output.printlnInstruction(toString(mnemonic), operands, 0, 2);
goto continue_label1;
end;
begin
if __type.isFloating() then begin
mnmnc := 'jsltl';
end else begin
mnmnc := 'jslt';
end;
writer.&set(mnemonic).writeString(mnmnc).writeSignature(__type, STACK).writeString(suffix).trim();
operands[0] := writer.&set(operandA).writeLabel(jumpIsFalse).get();
operands[1] := toString(operandB);
if itemT = nil then begin
output.printlnInstruction(toString(mnemonic), operands, 0, 1);
end else begin
output.printlnInstruction(toString(mnemonic), operands, 0, 2);
end;
end;
if jumpIsTrue.order <> order then begin
writer.&set(operandA).writeLabel(jumpIsTrue).trim();
output.printlnInstruction('jmp', toString(operandA));
end;
goto continue_label1;
end;
if itemT = nil then begin
if kindOfResultType <= TYP_VOID then begin
suffix := '_p';
end else begin
suffix := '';
end;
writer.&set(mnemonic).writeString('setsge').writeSignature(__type, STACK).writeString(suffix).trim();
output.printlnInstruction(toString(mnemonic));
goto continue_label1;
end;
writer.&set(mnemonic).writeString('setsge').writeSignature(__type, STACK).writeString(suffix).trim();
output.printlnInstruction(toString(mnemonic), toString(operandB));
goto break_labelPush;
end;
O_SCAL_LT: begin
__type := __node.operand1 as PrimitiveType;
itemI := __node.operand2;
itemC := __node.operandC;
itemT := getTypedItem(itemC, ItemI);
suffix := additionalToFasmString(itemC, itemI, operandB, refsTable);
if isConditionalJump then begin
order := __node.order + 1;
if jumpIsFalse.order = order then begin
if __type.isFloating() then begin
mnmnc := 'jsltg';
end else begin
mnmnc := 'jslt';
end;
writer.&set(mnemonic).writeString(mnmnc).writeSignature(__type, STACK).writeString(suffix).trim();
operands[0] := writer.&set(operandA).writeLabel(jumpIsTrue).get();
operands[1] := toString(operandB);
if itemT = nil then begin
output.printlnInstruction(toString(mnemonic), operands, 0, 1);
goto continue_label1;
end;
output.printlnInstruction(toString(mnemonic), operands, 0, 2);
goto continue_label1;
end;
begin
if __type.isFloating() then begin
mnmnc := 'jsgeg';
end else begin
mnmnc := 'jsge';
end;
writer.&set(mnemonic).writeString(mnmnc).writeSignature(__type, STACK).writeString(suffix).trim();
operands[0] := writer.&set(operandA).writeLabel(jumpIsFalse).get();
operands[1] := toString(operandB);
if itemT = nil then begin
output.printlnInstruction(toString(mnemonic), operands, 0, 1);
end else begin
output.printlnInstruction(toString(mnemonic), operands, 0, 2);
end;
end;
if jumpIsTrue.order <> order then begin
writer.&set(operandA).writeLabel(jumpIsTrue).trim();
output.printlnInstruction('jmp', toString(operandA));
end;
goto continue_label1;
end;
if itemT = nil then begin
if kindOfResultType <= TYP_VOID then begin
suffix := '_p';
end else begin
suffix := '';
end;
writer.&set(mnemonic).writeString('setslt').writeSignature(__type, STACK).writeString(suffix).trim();
output.printlnInstruction(toString(mnemonic));
goto continue_label1;
end;
writer.&set(mnemonic).writeString('setslt').writeSignature(__type, STACK).writeString(suffix).trim();
output.printlnInstruction(toString(mnemonic), toString(operandB));
goto break_labelPush;
end;
O_SCAL_LE: begin
__type := __node.operand1 as PrimitiveType;
itemI := __node.operand2;
itemC := __node.operandC;
itemT := getTypedItem(itemC, ItemI);
suffix := additionalToFasmString(itemC, itemI, operandB, refsTable);
if isConditionalJump then begin
order := __node.order + 1;
if jumpIsFalse.order = order then begin
if __type.isFloating() then begin
mnmnc := 'jsleg';
end else begin
mnmnc := 'jsle';
end;
writer.&set(mnemonic).writeString(mnmnc).writeSignature(__type, STACK).writeString(suffix).trim();
operands[0] := writer.&set(operandA).writeLabel(jumpIsTrue).get();
operands[1] := toString(operandB);
if itemT = nil then begin
output.printlnInstruction(toString(mnemonic), operands, 0, 1);
goto continue_label1;
end;
output.printlnInstruction(toString(mnemonic), operands, 0, 2);
goto continue_label1;
end;
begin
if __type.isFloating() then begin
mnmnc := 'jsgtg';
end else begin
mnmnc := 'jsgt';
end;
writer.&set(mnemonic).writeString(mnmnc).writeSignature(__type, STACK).writeString(suffix).trim();
operands[0] := writer.&set(operandA).writeLabel(jumpIsFalse).get();
operands[1] := toString(operandB);
if itemT = nil then begin
output.printlnInstruction(toString(mnemonic), operands, 0, 1);
end else begin
output.printlnInstruction(toString(mnemonic), operands, 0, 2);
end;
end;
if jumpIsTrue.order <> order then begin
writer.&set(operandA).writeLabel(jumpIsTrue).trim();
output.printlnInstruction('jmp', toString(operandA));
end;
goto continue_label1;
end;
if itemT = nil then begin
if kindOfResultType <= TYP_VOID then begin
suffix := '_p';
end else begin
suffix := '';
end;
writer.&set(mnemonic).writeString('setsle').writeSignature(__type, STACK).writeString(suffix).trim();
output.printlnInstruction(toString(mnemonic));
goto continue_label1;
end;
writer.&set(mnemonic).writeString('setsle').writeSignature(__type, STACK).writeString(suffix).trim();
output.printlnInstruction(toString(mnemonic), toString(operandB));
goto break_labelPush;
end;
O_VECT_LUP: begin
__type := __node.operand1 as PrimitiveType;
writer.&set(mnemonic).writeString('vlup').writeSignature(__type, NORM).trim();
output.printlnInstruction(toString(mnemonic));
kindOfPushType := __type.kind + (TYP_SHORT - TYP_BYTE);
goto break_labelPush;
end;
O_VECT_UUP: begin
__type := __node.operand1 as PrimitiveType;
writer.&set(mnemonic).writeString('vuup').writeSignature(__type, NORM).trim();
output.printlnInstruction(toString(mnemonic));
kindOfPushType := __type.kind + (TYP_SHORT - TYP_BYTE);
goto break_labelPush;
end;
O_VECT_PCK: begin
__type := __node.operand1 as PrimitiveType;
writer.&set(mnemonic).writeString('vpck').writeSignature(__type, NORM).trim();
output.printlnInstruction(toString(mnemonic));
kindOfPushType := __type.kind + (TYP_BYTE - TYP_SHORT);
goto break_labelPush;
end;
O_VECT_NEG: begin
__type := __node.operand1 as PrimitiveType;
writer.&set(mnemonic).writeString('vneg').writeSignature(__type, NORM).trim();
output.printlnInstruction(toString(mnemonic));
kindOfPushType := __type.kind;
goto break_labelPush;
end;
O_VECT_MUL: begin
__type := __node.operand1 as PrimitiveType;
itemI := __node.operand2;
itemC := __node.operandC;
itemT := getTypedItem(itemC, itemI);
suffix := additionalToFasmString(itemC, itemI, operandA, refsTable);
if itemT = nil then begin
if kindOfResultType <= TYP_VOID then begin
suffix := '_p';
end else begin
suffix := '';
end;
writer.&set(mnemonic).writeString('vmul').writeSignature(__type, NORM).writeString(suffix).trim();
output.printlnInstruction(toString(mnemonic));
goto continue_label1;
end;
writer.&set(mnemonic).writeString('vmul').writeSignature(__type, NORM).writeString(suffix).trim();
output.printlnInstruction(toString(mnemonic), toString(operandA));
kindOfPushType := __type.kind;
goto break_labelPush;
end;
O_VECT_DIV: begin
__type := __node.operand1 as PrimitiveType;
itemI := __node.operand2;
itemC := __node.operandC;
itemT := getTypedItem(itemC, itemI);
suffix := additionalToFasmString(itemC, itemI, operandA, refsTable);
if itemT = nil then begin
if kindOfResultType <= TYP_VOID then begin
suffix := '_p';
end else begin
suffix := '';
end;
writer.&set(mnemonic).writeString('vdiv').writeSignature(__type, NORM).writeString(suffix).trim();
output.printlnInstruction(toString(mnemonic));
goto continue_label1;
end;
writer.&set(mnemonic).writeString('vdiv').writeSignature(__type, NORM).writeString(suffix).trim();
output.printlnInstruction(toString(mnemonic), toString(operandA));
if not __type.isFloating() then begin
kindOfPushType := TYP_DOUBLE or __type.kind and 3;
goto break_labelPush;
end;
kindOfPushType := __type.kind;
goto break_labelPush;
end;
O_VECT_ADD: begin
__type := __node.operand1 as PrimitiveType;
itemI := __node.operand2;
itemC := __node.operandC;
itemT := getTypedItem(itemC, itemI);
suffix := additionalToFasmString(itemC, itemI, operandA, refsTable);
if itemT = nil then begin
if kindOfResultType <= TYP_VOID then begin
suffix := '_p';
end else begin
suffix := '';
end;
writer.&set(mnemonic).writeString('vadd').writeSignature(__type, NORM).writeString(suffix).trim();
output.printlnInstruction(toString(mnemonic));
goto continue_label1;
end;
writer.&set(mnemonic).writeString('vadd').writeSignature(__type, NORM).writeString(suffix).trim();
output.printlnInstruction(toString(mnemonic), toString(operandA));
kindOfPushType := __type.kind;
goto break_labelPush;
end;
O_VECT_SUB: begin
__type := __node.operand1 as PrimitiveType;
itemI := __node.operand2;
itemC := __node.operandC;
itemT := getTypedItem(itemC, itemI);
suffix := additionalToFasmString(itemC, itemI, operandA, refsTable);
if itemT = nil then begin
if kindOfResultType <= TYP_VOID then begin
suffix := '_p';
end else begin
suffix := '';
end;
writer.&set(mnemonic).writeString('vsub').writeSignature(__type, NORM).writeString(suffix).trim();
output.printlnInstruction(toString(mnemonic));
goto continue_label1;
end;
writer.&set(mnemonic).writeString('vsub').writeSignature(__type, NORM).writeString(suffix).trim();
output.printlnInstruction(toString(mnemonic), toString(operandA));
kindOfPushType := __type.kind;
goto break_labelPush;
end;
O_VECT_SHR: begin
__type := __node.operand1 as PrimitiveType;
itemI := __node.operand2;
itemC := __node.operandC;
itemT := getTypedItem(itemC, itemI);
suffix := additionalToFasmString(itemC, itemI, operandA, refsTable);
if itemT = nil then begin
if kindOfResultType <= TYP_VOID then begin
suffix := '_p';
end else begin
suffix := '';
end;
writer.&set(mnemonic).writeString('vshr').writeSignature(__type, NORM).writeString(suffix).trim();
output.printlnInstruction(toString(mnemonic));
goto continue_label1;
end;
writer.&set(mnemonic).writeString('vshr').writeSignature(__type, NORM).writeString(suffix).trim();
output.printlnInstruction(toString(mnemonic), toString(operandA));
kindOfPushType := __type.kind;
goto break_labelPush;
end;
O_VECT_SHRU: begin
__type := __node.operand1 as PrimitiveType;
itemI := __node.operand2;
itemC := __node.operandC;
itemT := getTypedItem(itemC, itemI);
suffix := additionalToFasmString(itemC, itemI, operandA, refsTable);
if itemT = nil then begin
if kindOfResultType <= TYP_VOID then begin
suffix := '_p';
end else begin
suffix := '';
end;
writer.&set(mnemonic).writeString('vshru').writeSignature(__type, NORM).writeString(suffix).trim();
output.printlnInstruction(toString(mnemonic));
goto continue_label1;
end;
writer.&set(mnemonic).writeString('vshru').writeSignature(__type, NORM).writeString(suffix).trim();
output.printlnInstruction(toString(mnemonic), toString(operandA));
kindOfPushType := __type.kind;
goto break_labelPush;
end;
O_VECT_SHL: begin
__type := __node.operand1 as PrimitiveType;
itemI := __node.operand2;
itemC := __node.operandC;
itemT := getTypedItem(itemC, itemI);
suffix := additionalToFasmString(itemC, itemI, operandA, refsTable);
if itemT = nil then begin
if kindOfResultType <= TYP_VOID then begin
suffix := '_p';
end else begin
suffix := '';
end;
writer.&set(mnemonic).writeString('vshl').writeSignature(__type, NORM).writeString(suffix).trim();
output.printlnInstruction(toString(mnemonic));
goto continue_label1;
end;
writer.&set(mnemonic).writeString('vshl').writeSignature(__type, NORM).writeString(suffix).trim();
output.printlnInstruction(toString(mnemonic), toString(operandA));
kindOfPushType := __type.kind;
goto break_labelPush;
end;
O_VECT_EQ: begin
__type := __node.operand1 as PrimitiveType;
itemI := __node.operand2;
itemC := __node.operandC;
itemT := getTypedItem(itemC, itemI);
suffix := additionalToFasmString(itemC, itemI, operandA, refsTable);
if itemT = nil then begin
if kindOfResultType <= TYP_VOID then begin
suffix := '_p';
end else begin
suffix := '';
end;
writer.&set(mnemonic).writeString('veq').writeSignature(__type, NORM).writeString(suffix).trim();
output.printlnInstruction(toString(mnemonic));
goto continue_label1;
end;
writer.&set(mnemonic).writeString('veq').writeSignature(__type, NORM).writeString(suffix).trim();
output.printlnInstruction(toString(mnemonic), toString(operandA));
kindOfPushType := __type.kind;
if (kindOfPushType >= TYP_DOUBLE) and (kindOfPushType <= TYP_DOUBLE8) then begin
inc(kindOfPushType, TYP_LONG - TYP_DOUBLE);
goto break_labelPush;
end;
if (kindOfPushType >= TYP_FLOAT) and (kindOfPushType <= TYP_FLOAT8) then begin
inc(kindOfPushType, TYP_INT - TYP_FLOAT);
end;
goto break_labelPush;
end;
O_VECT_NE: begin
__type := __node.operand1 as PrimitiveType;
itemI := __node.operand2;
itemC := __node.operandC;
itemT := getTypedItem(itemC, itemI);
suffix := additionalToFasmString(itemC, itemI, operandA, refsTable);
if itemT = nil then begin
if kindOfResultType <= TYP_VOID then begin
suffix := '_p';
end else begin
suffix := '';
end;
writer.&set(mnemonic).writeString('vne').writeSignature(__type, NORM).writeString(suffix).trim();
output.printlnInstruction(toString(mnemonic));
goto continue_label1;
end;
writer.&set(mnemonic).writeString('vne').writeSignature(__type, NORM).writeString(suffix).trim();
output.printlnInstruction(toString(mnemonic), toString(operandA));
kindOfPushType := __type.kind;
if (kindOfPushType >= TYP_DOUBLE) and (kindOfPushType <= TYP_DOUBLE8) then begin
inc(kindOfPushType, TYP_LONG - TYP_DOUBLE);
goto break_labelPush;
end;
if (kindOfPushType >= TYP_FLOAT) and (kindOfPushType <= TYP_FLOAT8) then begin
inc(kindOfPushType, TYP_INT - TYP_FLOAT);
end;
goto break_labelPush;
end;
O_VECT_GT: begin
__type := __node.operand1 as PrimitiveType;
itemI := __node.operand2;
itemC := __node.operandC;
itemT := getTypedItem(itemC, itemI);
suffix := additionalToFasmString(itemC, itemI, operandA, refsTable);
if itemT = nil then begin
if kindOfResultType <= TYP_VOID then begin
suffix := '_p';
end else begin
suffix := '';
end;
writer.&set(mnemonic).writeString('vgt').writeSignature(__type, NORM).writeString(suffix).trim();
output.printlnInstruction(toString(mnemonic));
goto continue_label1;
end;
writer.&set(mnemonic).writeString('vgt').writeSignature(__type, NORM).writeString(suffix).trim();
output.printlnInstruction(toString(mnemonic), toString(operandA));
kindOfPushType := __type.kind;
if (kindOfPushType >= TYP_DOUBLE) and (kindOfPushType <= TYP_DOUBLE8) then begin
inc(kindOfPushType, TYP_LONG - TYP_DOUBLE);
goto break_labelPush;
end;
if (kindOfPushType >= TYP_FLOAT) and (kindOfPushType <= TYP_FLOAT8) then begin
inc(kindOfPushType, TYP_INT - TYP_FLOAT);
end;
goto break_labelPush;
end;
O_VECT_GE: begin
__type := __node.operand1 as PrimitiveType;
itemI := __node.operand2;
itemC := __node.operandC;
itemT := getTypedItem(itemC, itemI);
suffix := additionalToFasmString(itemC, itemI, operandA, refsTable);
if itemT = nil then begin
if kindOfResultType <= TYP_VOID then begin
suffix := '_p';
end else begin
suffix := '';
end;
writer.&set(mnemonic).writeString('vge').writeSignature(__type, NORM).writeString(suffix).trim();
output.printlnInstruction(toString(mnemonic));
goto continue_label1;
end;
writer.&set(mnemonic).writeString('vge').writeSignature(__type, NORM).writeString(suffix).trim();
output.printlnInstruction(toString(mnemonic), toString(operandA));
kindOfPushType := __type.kind;
if (kindOfPushType >= TYP_DOUBLE) and (kindOfPushType <= TYP_DOUBLE8) then begin
inc(kindOfPushType, TYP_LONG - TYP_DOUBLE);
goto break_labelPush;
end;
if (kindOfPushType >= TYP_FLOAT) and (kindOfPushType <= TYP_FLOAT8) then begin
inc(kindOfPushType, TYP_INT - TYP_FLOAT);
end;
goto break_labelPush;
end;
O_VECT_LT: begin
__type := __node.operand1 as PrimitiveType;
itemI := __node.operand2;
itemC := __node.operandC;
itemT := getTypedItem(itemC, itemI);
suffix := additionalToFasmString(itemC, itemI, operandA, refsTable);
if itemT = nil then begin
if kindOfResultType <= TYP_VOID then begin
suffix := '_p';
end else begin
suffix := '';
end;
writer.&set(mnemonic).writeString('vlt').writeSignature(__type, NORM).writeString(suffix).trim();
output.printlnInstruction(toString(mnemonic));
goto continue_label1;
end;
writer.&set(mnemonic).writeString('vlt').writeSignature(__type, NORM).writeString(suffix).trim();
output.printlnInstruction(toString(mnemonic), toString(operandA));
kindOfPushType := __type.kind;
if (kindOfPushType >= TYP_DOUBLE) and (kindOfPushType <= TYP_DOUBLE8) then begin
inc(kindOfPushType, TYP_LONG - TYP_DOUBLE);
goto break_labelPush;
end;
if (kindOfPushType >= TYP_FLOAT) and (kindOfPushType <= TYP_FLOAT8) then begin
inc(kindOfPushType, TYP_INT - TYP_FLOAT);
end;
goto break_labelPush;
end;
O_VECT_LE: begin
__type := __node.operand1 as PrimitiveType;
itemI := __node.operand2;
itemC := __node.operandC;
itemT := getTypedItem(itemC, itemI);
suffix := additionalToFasmString(itemC, itemI, operandA, refsTable);
if itemT = nil then begin
if kindOfResultType <= TYP_VOID then begin
suffix := '_p';
end else begin
suffix := '';
end;
writer.&set(mnemonic).writeString('vle').writeSignature(__type, NORM).writeString(suffix).trim();
output.printlnInstruction(toString(mnemonic));
goto continue_label1;
end;
writer.&set(mnemonic).writeString('vle').writeSignature(__type, NORM).writeString(suffix).trim();
output.printlnInstruction(toString(mnemonic), toString(operandA));
kindOfPushType := __type.kind;
if (kindOfPushType >= TYP_DOUBLE) and (kindOfPushType <= TYP_DOUBLE8) then begin
inc(kindOfPushType, TYP_LONG - TYP_DOUBLE);
goto break_labelPush;
end;
if (kindOfPushType >= TYP_FLOAT) and (kindOfPushType <= TYP_FLOAT8) then begin
inc(kindOfPushType, TYP_INT - TYP_FLOAT);
end;
goto break_labelPush;
end;
O_VECT_HMUL: begin
__type := __node.operand1 as PrimitiveType;
itemI := __node.operand2;
itemC := __node.operandC;
itemT := getTypedItem(itemC, itemI);
suffix := additionalToFasmString(itemC, itemI, operandA, refsTable);
if itemT = nil then begin
if kindOfResultType <= TYP_VOID then begin
suffix := '_p';
end else begin
suffix := '';
end;
writer.&set(mnemonic).writeString('vhmul').writeSignature(__type, NORM).writeString(suffix).trim();
output.printlnInstruction(toString(mnemonic));
goto continue_label1;
end;
writer.&set(mnemonic).writeString('vhmul').writeSignature(__type, NORM).writeString(suffix).trim();
output.printlnInstruction(toString(mnemonic), toString(operandA));
kindOfPushType := __type.kind;
goto break_labelPush;
end;
O_VECT_HMULU: begin
__type := __node.operand1 as PrimitiveType;
itemI := __node.operand2;
itemC := __node.operandC;
itemT := getTypedItem(itemC, itemI);
suffix := additionalToFasmString(itemC, itemI, operandA, refsTable);
if itemT = nil then begin
if kindOfResultType <= TYP_VOID then begin
suffix := '_p';
end else begin
suffix := '';
end;
writer.&set(mnemonic).writeString('vhmulu').writeSignature(__type, NORM).writeString(suffix).trim();
output.printlnInstruction(toString(mnemonic));
goto continue_label1;
end;
writer.&set(mnemonic).writeString('vhmulu').writeSignature(__type, NORM).writeString(suffix).trim();
output.printlnInstruction(toString(mnemonic), toString(operandA));
kindOfPushType := __type.kind;
goto break_labelPush;
end;
O_VECT_SADD: begin
__type := __node.operand1 as PrimitiveType;
itemI := __node.operand2;
itemC := __node.operandC;
itemT := getTypedItem(itemC, itemI);
suffix := additionalToFasmString(itemC, itemI, operandA, refsTable);
if itemT = nil then begin
if kindOfResultType <= TYP_VOID then begin
suffix := '_p';
end else begin
suffix := '';
end;
writer.&set(mnemonic).writeString('vsadd').writeSignature(__type, NORM).writeString(suffix).trim();
output.printlnInstruction(toString(mnemonic));
goto continue_label1;
end;
writer.&set(mnemonic).writeString('vsadd').writeSignature(__type, NORM).writeString(suffix).trim();
output.printlnInstruction(toString(mnemonic), toString(operandA));
kindOfPushType := __type.kind;
goto break_labelPush;
end;
O_VECT_SADDU: begin
__type := __node.operand1 as PrimitiveType;
itemI := __node.operand2;
itemC := __node.operandC;
itemT := getTypedItem(itemC, itemI);
suffix := additionalToFasmString(itemC, itemI, operandA, refsTable);
if itemT = nil then begin
if kindOfResultType <= TYP_VOID then begin
suffix := '_p';
end else begin
suffix := '';
end;
writer.&set(mnemonic).writeString('vsaddu').writeSignature(__type, NORM).writeString(suffix).trim();
output.printlnInstruction(toString(mnemonic));
goto continue_label1;
end;
writer.&set(mnemonic).writeString('vsaddu').writeSignature(__type, NORM).writeString(suffix).trim();
output.printlnInstruction(toString(mnemonic), toString(operandA));
kindOfPushType := __type.kind;
goto break_labelPush;
end;
O_VECT_SSUB: begin
__type := __node.operand1 as PrimitiveType;
itemI := __node.operand2;
itemC := __node.operandC;
itemT := getTypedItem(itemC, itemI);
suffix := additionalToFasmString(itemC, itemI, operandA, refsTable);
if itemT = nil then begin
if kindOfResultType <= TYP_VOID then begin
suffix := '_p';
end else begin
suffix := '';
end;
writer.&set(mnemonic).writeString('vssub').writeSignature(__type, NORM).writeString(suffix).trim();
output.printlnInstruction(toString(mnemonic));
goto continue_label1;
end;
writer.&set(mnemonic).writeString('vssub').writeSignature(__type, NORM).writeString(suffix).trim();
output.printlnInstruction(toString(mnemonic), toString(operandA));
kindOfPushType := __type.kind;
goto break_labelPush;
end;
O_VECT_SSUBU: begin
__type := __node.operand1 as PrimitiveType;
itemI := __node.operand2;
itemC := __node.operandC;
itemT := getTypedItem(itemC, itemI);
suffix := additionalToFasmString(itemC, itemI, operandA, refsTable);
if itemT = nil then begin
if kindOfResultType <= TYP_VOID then begin
suffix := '_p';
end else begin
suffix := '';
end;
writer.&set(mnemonic).writeString('vssubu').writeSignature(__type, NORM).writeString(suffix).trim();
output.printlnInstruction(toString(mnemonic));
goto continue_label1;
end;
writer.&set(mnemonic).writeString('vssubu').writeSignature(__type, NORM).writeString(suffix).trim();
output.printlnInstruction(toString(mnemonic), toString(operandA));
kindOfPushType := __type.kind;
goto break_labelPush;
end;
STORE_LOCAL: begin
__local := __node.operand1 as Local;
itemI := __node.operand2;
itemC := __node.operandC;
name := __local.fasmSimpleName;
if itemC = nil then begin
if itemI = nil then begin
__type := __local.&type;
end else begin
__type := itemI as &Type;
end;
writer.&set(mnemonic).writeString('store').writeSignature(__type, STACK).writeString('_l').trim();
if __type.isPrimitive() or not refsTable.contains(name) then begin
operands[0] := name;
end else begin
operands[0] := writer.&set(operandA).writeChar('$').writeString(name).get();
end;
output.printlnInstruction(toString(mnemonic), operands, 0, 1);
goto break_labelPop;
end;
__type := itemC.&type;
constantToFasmString(itemC, operandB);
writer.&set(mnemonic).writeString('store').writeSignature(__type, STACK).writeString('_lc').trim();
if __type.isPrimitive() or not refsTable.contains(name) then begin
operands[0] := name;
end else begin
operands[0] := writer.&set(operandA).writeChar('$').writeString(name).get();
end;
operands[1] := toString(operandB);
output.printlnInstruction(toString(mnemonic), operands, 0, 2);
goto break_labelPop;
end;
DECLARE_LOCAL,
DECLARE_WITH: begin
__local := __node.operand1 as Local;
itemI := __node.operand2;
itemC := __node.operandC;
name := __local.fasmSimpleName;
if itemC = nil then begin
if itemI = nil then begin
__type := __local.&type;
end else begin
__type := itemI as &Type;
end;
writer.&set(mnemonic).writeString('declare').writeSignature(__type, STACK).trim();
if __type.isPrimitive() or not refsTable.contains(name) then begin
operands[0] := name;
end else begin
operands[0] := writer.&set(operandA).writeChar('$').writeString(name).get();
end;
output.printlnInstruction(toString(mnemonic), operands, 0, 1);
goto break_labelPop;
end;
__type := itemC.&type;
constantToFasmString(itemC, operandB);
writer.&set(mnemonic).writeString('declare').writeSignature(__type, STACK).writeString('_c').trim();
if __type.isPrimitive() or not refsTable.contains(name) then begin
operands[0] := name;
end else begin
operands[0] := writer.&set(operandA).writeChar('$').writeString(name).get();
end;
operands[1] := toString(operandB);
output.printlnInstruction(toString(mnemonic), operands, 0, 2);
goto break_labelPop;
end;
STORE_STATIC: begin
__global := __node.operand1 as Field;
__value := __node.operandC;
if __value = nil then begin
writer.&set(mnemonic).writeString('store').writeSignature(__global.&type, STACK).writeString('_g').trim();
writer.&set(operandA).writeChar('[').writeString(__global.fasmFullName).writeChar(']').trim();
output.printlnInstruction(toString(mnemonic), toString(operandA));
goto break_labelPop;
end;
constantToFasmString(__value, operandB);
writer.&set(mnemonic).writeString('store').writeSignature(__global.&type, STACK).writeString('_gc').trim();
operands[0] := writer.&set(operandA).writeChar('[').writeString(__global.fasmFullName).writeChar(']').get();
operands[1] := toString(operandB);
output.printlnInstruction(toString(mnemonic), operands, 0, 2);
goto break_labelPop;
end;
WRITE_COMPONENT: begin
__type := __node.operand1 as &Type;
writer.&set(mnemonic).writeString('wrac').writeSignature(__type, NORM).trim();
output.printlnInstruction(toString(mnemonic));
goto break_labelPop;
end;
WRITE_FIELD: begin
__field := __node.operand1 as Field;
__type := __field.&type;
if __field.parentType.isStruct() and __type.isPrimitive() then begin
mnmnc := 'wrsf';
end else begin
mnmnc := 'wrif';
end;
writer.&set(mnemonic).writeString(mnmnc).writeSignature(__type, NORM).trim();
output.printlnInstruction(toString(mnemonic), __field.fasmFullName);
goto break_labelPop;
end;
WRITE_SPECIAL: begin
__property := __node.operand1 as &Property;
synthetic := __property.writeSynthetic;
if not __property.hasIndex() then begin
__member := __property.writeMember;
if Lang.isInstance(__member, Field) then begin
__field := Field(Lang.cast(__member, Field));
__type := __field.&type;
if __field.parentType.isStruct() and __type.isPrimitive() then begin
mnmnc := 'wrsf';
end else begin
mnmnc := 'wrif';
end;
writer.&set(mnemonic).writeString(mnmnc).writeSignature(__type, NORM).trim();
output.printlnInstruction(toString(mnemonic), __field.fasmFullName);
goto break_labelPop;
end;
if Lang.isInstance(__member, Callable) then begin
__methodc := Callable(Lang.cast(__member, Callable));
if __methodc.serviceIndex >= 0 then begin
operands[0] := __methodc.parentType.fasmFullName;
operands[1] := writer.&set(operandA).writeString(__methodc.fasmSimpleName).writeString(__methodc.arguments.toFasmString()).get();
output.printlnInstruction('invserv', operands, 0, 2);
goto break_labelPop;
end;
if __methodc.virtualIndex >= 0 then begin
output.printlnInstruction('invvirt', __methodc.fasmFullName);
goto break_labelPop;
end;
output.printlnInstruction('invspec', __methodc.fasmFullName);
goto break_labelPop;
end;
end;
output.printlnInstruction('invspec', synthetic.fasmFullName);
goto break_labelPop;
end;
WRITE_PROPERTY: begin
__property := __node.operand1 as &Property;
synthetic := __property.writeSynthetic;
sindex := synthetic.serviceIndex;
vindex := synthetic.virtualIndex;
if not __property.hasIndex() and ((sindex and vindex) < 0) then begin
__member := __property.writeMember;
if Lang.isInstance(__member, Field) then begin
__field := Field(Lang.cast(__member, Field));
__type := __field.&type;
if __field.parentType.isStruct() and __type.isPrimitive() then begin
mnmnc := 'wrsf';
end else begin
mnmnc := 'wrif';
end;
writer.&set(mnemonic).writeString(mnmnc).writeSignature(__type, NORM).trim();
output.printlnInstruction(toString(mnemonic), __field.fasmFullName);
goto break_labelPop;
end;
if Lang.isInstance(__member, Callable) then begin
__methodc := Callable(Lang.cast(__member, Callable));
if __methodc.serviceIndex >= 0 then begin
operands[0] := __methodc.parentType.fasmFullName;
operands[1] := writer.&set(operandA).writeString(__methodc.fasmSimpleName).writeString(__methodc.arguments.toFasmString()).get();
output.printlnInstruction('invserv', operands, 0, 2);
goto break_labelPop;
end;
if __methodc.virtualIndex >= 0 then begin
output.printlnInstruction('invvirt', __methodc.fasmFullName);
goto break_labelPop;
end;
output.printlnInstruction('invspec', __methodc.fasmFullName);
goto break_labelPop;
end;
end;
if sindex >= 0 then begin
operands[0] := synthetic.parentType.fasmFullName;
operands[1] := writer.&set(operandA).writeString(synthetic.fasmSimpleName).writeString(synthetic.arguments.toFasmString()).get();
output.printlnInstruction('invserv', operands, 0, 2);
goto break_labelPop;
end;
if vindex >= 0 then begin
output.printlnInstruction('invvirt', synthetic.fasmFullName);
goto break_labelPop;
end;
output.printlnInstruction('invspec', synthetic.fasmFullName);
goto break_labelPop;
end;
EXCEPT_ENTER: begin
output.printlnInstruction('eenter');
goto continue_label1;
end;
EXCEPT_TRY: begin
if anonymus then output.printLabel('');
operands[0] := writer.&set(operandA).writeLabel(__node.reference1 as Node).get();
operands[1] := writer.&set(operandB).writeLabel(__node.reference2 as Node).get();
operands[2] := '@F';
output.printlnInstruction('try', operands, 0, 3);
anonymus := true;
goto continue_label1;
end;
EXCEPT_CATCH: begin
operands[0] := (__node.reference2 as ru.malik.elaborarer.avtoo.lang.ClassType).fasmFullName;
operands[1] := writer.&set(operandA).writeLabel(__node.reference1 as Node).get();
output.printlnInstruction('catch', operands, 0, 2);
goto continue_label1;
end;
EXCEPT_FINALLY: begin
writer.&set(operandA).writeLabel(__node.reference1 as Node).trim();
output.printlnInstruction('finally', toString(operandA));
goto continue_label1;
end;
EXCEPT_LEAVE: begin
if anonymus then output.printLabel('');
output.printlnInstruction('eleave');
goto continue_label1;
end;
end;
break_label2:
if isConditionalJump then begin
order := __node.order + 1;
if jumpIsFalse.order = order then begin
writer.&set(operandA).writeLabel(jumpIsTrue).trim();
output.printlnInstruction('jt', toString(operandA));
goto continue_label1;
end;
begin
writer.&set(operandA).writeLabel(jumpIsFalse).trim();
output.printlnInstruction('jf', toString(operandA));
end;
if jumpIsTrue.order <> order then begin
writer.&set(operandA).writeLabel(jumpIsTrue).trim();
output.printlnInstruction('jmp', toString(operandA));
end;
goto continue_label1;
end;
end;
break_labelPush:
if kindOfResultType <= TYP_VOID then begin
writer.&set(mnemonic).writeString('tpush').writeSignature(kindOfPushType, STACK).trim();
output.printlnInstruction(toString(mnemonic));
end;
goto continue_label1;
end;
break_labelPop:
if kindOfResultType > TYP_VOID then begin
writer.&set(mnemonic).writeString('tpop').writeSignature(kindOfResultType, STACK).trim();
output.printlnInstruction(toString(mnemonic));
end;
end;
break_labelConj:
if isConditionalJump then begin
order := __node.order + 1;
if jumpIsFalse.order = order then begin
writer.&set(operandA).writeLabel(jumpIsTrue).trim();
output.printlnInstruction('jt', toString(operandA));
goto continue_label1;
end;
begin
writer.&set(operandA).writeLabel(jumpIsFalse).trim();
output.printlnInstruction('jf', toString(operandA));
end;
if jumpIsTrue.order <> order then begin
writer.&set(operandA).writeLabel(jumpIsTrue).trim();
output.printlnInstruction('jmp', toString(operandA));
end;
end;
continue_label1:
__node := __next;
end;
finally
refsTable.free();
refsTable := nil;
end;
end;
break_label0:
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.decreaseMargin();
output.printlnHeader('end if ; </fold>');
end;
procedure AssemblerSourceGenerator.generateImplementorCode(__type, __superservice: ClassType; output: AssemblerSourcePrintStream);
var
index: int;
mnemonic: AnsiString;
operands: AnsiString_Array1d;
methods: Callable_Array1d;
__method: Callable;
begin
operands := &Array.newAnsiString1d(2);
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.printHeader('; <fold ');
output.print(__superservice.specialCanonicalName);
output.println('>');
output.increaseMargin();
{ -------------------------------------------------------------------------------------------------------------------------------- }
operands[0] := __type.fasmFullName;
operands[1] := __superservice.fasmFullName;
output.printlnInstruction('impl', operands, 0, 2);
{ -------------------------------------------------------------------------------------------------------------------------------- }
methods := __superservice.serviceCallables();
for index := 0 to system.length(methods) - 1 do begin
__method := methods[index].overridesIn(__type, Method.CURRENT_TYPE or Method.SUPERTYPES) as Callable;
if __method.virtualIndex < 0 then begin
mnemonic := 'jmpspec';
end else begin
mnemonic := 'jmpvirt';
end;
output.printlnInstruction(mnemonic, __method.fasmFullName);
end;
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.decreaseMargin();
output.printlnHeader('; </fold>');
end;
procedure AssemblerSourceGenerator.generateConstants(output: AssemblerSourcePrintStream);
type
Value_Array1d = specialize DynamicArray<Value>;
var
slimit: int;
vlimit: int;
slower: int;
vlower: int;
sindex: int;
vindex: int;
vlength: int;
dummvalue: long8;
b2value: byte2 absolute dummvalue;
b4value: byte4 absolute dummvalue;
b8value: byte8 absolute dummvalue;
s2value: short2 absolute dummvalue;
s4value: short4 absolute dummvalue;
s8value: short8 absolute dummvalue;
i2value: int2 absolute dummvalue;
i4value: int4 absolute dummvalue;
i8value: int8 absolute dummvalue;
l2value: long2 absolute dummvalue;
l4value: long4 absolute dummvalue;
l8value: long8 absolute dummvalue;
commstring: AnsiString;
stvalue: UnicodeString;
chars: uchar_Array1d;
operandA: char_Array1d;
fasmNums: char_Array2d;
commdata: Value_Array1d;
operands: AnsiString_Array1d;
writer: AssemblerElementWriter;
begin
writer := getAssemblerElementWriter();
operandA := &Array.newChar1d($0020);
fasmNums := &Array.newChar2d($0010, $0020);
operands := &Array.newAnsiString1d($10);
commdata := Value_Array1d(&Array.newIUnknown1d(1));
commstring := AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.generator.UNIT_NAME, 'comment.constants.type');
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.println();
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.printHeader('; <fold ');
output.print(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.generator.UNIT_NAME, 'comment.constants.programme'));
output.println('>');
output.increaseMargin();
{ -------------------------------------------------------------------------------------------------------------------------------- }
begin
commdata[0] := CoAnsiString.create('real');
output.printHeader('; <fold ');
output.print(AnsiString.format(commstring, commdata));
output.println('>');
output.increaseMargin();
{ -------------------------------------------------------------------------------------------------------------------------------- }
operands[0] := 'e';
operands[1] := writer.&set(operandA).writeByte($04).get();
output.printlnInstruction('cons', operands, 0, 2);
{ -------------------------------------------------------------------------------------------------------------------------------- }
with fldRealStorage do for sindex := 0 to getLength() - 1 do begin
l2value := VCoReal.toLong2Bits(readComponent(sindex));
for vindex := 0 to 4 do begin
operands[vindex] := writer.&set(fasmNums[vindex]).writeShort(s8value[vindex]).get();
end;
output.printlnInstruction('dw', operands, 0, 5);
end;
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.decreaseMargin();
output.printlnHeader('; </fold>');
end;
begin
output.println();
{ -------------------------------------------------------------------------------------------------------------------------------- }
commdata[0] := CoAnsiString.create('double');
output.printHeader('; <fold ');
output.print(AnsiString.format(commstring, commdata));
output.println('>');
output.increaseMargin();
{ -------------------------------------------------------------------------------------------------------------------------------- }
operands[0] := 'd';
operands[1] := writer.&set(operandA).writeByte($10).get();
output.printlnInstruction('cons', operands, 0, 2);
{ -------------------------------------------------------------------------------------------------------------------------------- }
with fldDoubleStorage do for sindex := 0 to getLength() - 1 do begin
begin
operands[0] := writer.&set(fasmNums[0]).writeLong(CoDouble.toLongBits(readComponent(sindex))).get();
end;
begin
operands[1] := writer.&set(fasmNums[1]).writeDecimal(0).get();
end;
output.printlnInstruction('dq', operands, 0, 2);
end;
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.decreaseMargin();
output.printlnHeader('; </fold>');
end;
begin
output.println();
{ -------------------------------------------------------------------------------------------------------------------------------- }
commdata[0] := CoAnsiString.create('double2');
output.printHeader('; <fold ');
output.print(AnsiString.format(commstring, commdata));
output.println('>');
output.increaseMargin();
{ -------------------------------------------------------------------------------------------------------------------------------- }
operands[0] := 'd2';
operands[1] := writer.&set(operandA).writeByte($10).get();
output.printlnInstruction('cons', operands, 0, 2);
{ -------------------------------------------------------------------------------------------------------------------------------- }
with fldDouble2Storage do for sindex := 0 to getLength() - 1 do begin
l2value := VCoDouble2.toLong2Bits(readComponent(sindex));
for vindex := 0 to 1 do begin
operands[vindex] := writer.&set(fasmNums[vindex]).writeLong(l2value[vindex]).get();
end;
output.printlnInstruction('dq', operands, 0, 2);
end;
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.decreaseMargin();
output.printlnHeader('; </fold>');
end;
begin
output.println();
{ -------------------------------------------------------------------------------------------------------------------------------- }
commdata[0] := CoAnsiString.create('double4');
output.printHeader('; <fold ');
output.print(AnsiString.format(commstring, commdata));
output.println('>');
output.increaseMargin();
{ -------------------------------------------------------------------------------------------------------------------------------- }
operands[0] := 'd4';
operands[1] := writer.&set(operandA).writeByte($20).get();
output.printlnInstruction('cons', operands, 0, 2);
{ -------------------------------------------------------------------------------------------------------------------------------- }
with fldDouble4Storage do for sindex := 0 to getLength() - 1 do begin
l4value := VCoDouble4.toLong4Bits(readComponent(sindex));
for vindex := 0 to 3 do begin
operands[vindex] := writer.&set(fasmNums[vindex]).writeLong(l4value[vindex]).get();
end;
output.printlnInstruction('dq', operands, 0, 4);
end;
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.decreaseMargin();
output.printlnHeader('; </fold>');
end;
begin
output.println();
{ -------------------------------------------------------------------------------------------------------------------------------- }
commdata[0] := CoAnsiString.create('double8');
output.printHeader('; <fold ');
output.print(AnsiString.format(commstring, commdata));
output.println('>');
output.increaseMargin();
{ -------------------------------------------------------------------------------------------------------------------------------- }
operands[0] := 'd8';
operands[1] := writer.&set(operandA).writeByte($40).get();
output.printlnInstruction('cons', operands, 0, 2);
{ -------------------------------------------------------------------------------------------------------------------------------- }
with fldDouble8Storage do for sindex := 0 to getLength() - 1 do begin
l8value := VCoDouble8.toLong8Bits(readComponent(sindex));
for vindex := 0 to 7 do begin
operands[vindex] := writer.&set(fasmNums[vindex]).writeLong(l8value[vindex]).get();
end;
output.printlnInstruction('dq', operands, 0, 8);
end;
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.decreaseMargin();
output.printlnHeader('; </fold>');
end;
begin
output.println();
{ -------------------------------------------------------------------------------------------------------------------------------- }
commdata[0] := CoAnsiString.create('float');
output.printHeader('; <fold ');
output.print(AnsiString.format(commstring, commdata));
output.println('>');
output.increaseMargin();
{ -------------------------------------------------------------------------------------------------------------------------------- }
operands[0] := 'f';
operands[1] := writer.&set(operandA).writeByte($10).get();
output.printlnInstruction('cons', operands, 0, 2);
{ -------------------------------------------------------------------------------------------------------------------------------- }
with fldFloatStorage do for sindex := 0 to getLength() - 1 do begin
begin
operands[0] := writer.&set(fasmNums[0]).writeInt(CoFloat.toIntBits(readComponent(sindex))).get();
end;
for vindex := 1 to 3 do begin
operands[vindex] := writer.&set(fasmNums[vindex]).writeDecimal(0).get();
end;
output.printlnInstruction('dd', operands, 0, 4);
end;
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.decreaseMargin();
output.printlnHeader('; </fold>');
end;
begin
output.println();
{ -------------------------------------------------------------------------------------------------------------------------------- }
commdata[0] := CoAnsiString.create('float2');
output.printHeader('; <fold ');
output.print(AnsiString.format(commstring, commdata));
output.println('>');
output.increaseMargin();
{ -------------------------------------------------------------------------------------------------------------------------------- }
operands[0] := 'f2';
operands[1] := writer.&set(operandA).writeByte($10).get();
output.printlnInstruction('cons', operands, 0, 2);
{ -------------------------------------------------------------------------------------------------------------------------------- }
with fldFloat2Storage do for sindex := 0 to getLength() - 1 do begin
i2value := VCoFloat2.toInt2Bits(readComponent(sindex));
for vindex := 0 to 1 do begin
operands[vindex] := writer.&set(fasmNums[vindex]).writeInt(i2value[vindex]).get();
end;
for vindex := 2 to 3 do begin
operands[vindex] := writer.&set(fasmNums[vindex]).writeDecimal(0).get();
end;
output.printlnInstruction('dd', operands, 0, 4);
end;
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.decreaseMargin();
output.printlnHeader('; </fold>');
end;
begin
output.println();
{ -------------------------------------------------------------------------------------------------------------------------------- }
commdata[0] := CoAnsiString.create('float4');
output.printHeader('; <fold ');
output.print(AnsiString.format(commstring, commdata));
output.println('>');
output.increaseMargin();
{ -------------------------------------------------------------------------------------------------------------------------------- }
operands[0] := 'f4';
operands[1] := writer.&set(operandA).writeByte($10).get();
output.printlnInstruction('cons', operands, 0, 2);
{ -------------------------------------------------------------------------------------------------------------------------------- }
with fldFloat4Storage do for sindex := 0 to getLength() - 1 do begin
i4value := VCoFloat4.toInt4Bits(readComponent(sindex));
for vindex := 0 to 3 do begin
operands[vindex] := writer.&set(fasmNums[vindex]).writeInt(i4value[vindex]).get();
end;
output.printlnInstruction('dd', operands, 0, 4);
end;
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.decreaseMargin();
output.printlnHeader('; </fold>');
end;
begin
output.println();
{ -------------------------------------------------------------------------------------------------------------------------------- }
commdata[0] := CoAnsiString.create('float8');
output.printHeader('; <fold ');
output.print(AnsiString.format(commstring, commdata));
output.println('>');
output.increaseMargin();
{ -------------------------------------------------------------------------------------------------------------------------------- }
operands[0] := 'f8';
operands[1] := writer.&set(operandA).writeByte($20).get();
output.printlnInstruction('cons', operands, 0, 2);
{ -------------------------------------------------------------------------------------------------------------------------------- }
with fldFloat8Storage do for sindex := 0 to getLength() - 1 do begin
i8value := VCoFloat8.toInt8Bits(readComponent(sindex));
for vindex := 0 to 7 do begin
operands[vindex] := writer.&set(fasmNums[vindex]).writeInt(i8value[vindex]).get();
end;
output.printlnInstruction('dd', operands, 0, 8);
end;
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.decreaseMargin();
output.printlnHeader('; </fold>');
end;
begin
output.println();
{ -------------------------------------------------------------------------------------------------------------------------------- }
commdata[0] := CoAnsiString.create('byte2');
output.printHeader('; <fold ');
output.print(AnsiString.format(commstring, commdata));
output.println('>');
output.increaseMargin();
{ -------------------------------------------------------------------------------------------------------------------------------- }
operands[0] := 'b2';
operands[1] := writer.&set(operandA).writeByte($10).get();
output.printlnInstruction('cons', operands, 0, 2);
{ -------------------------------------------------------------------------------------------------------------------------------- }
with fldByte2Storage do for sindex := 0 to getLength() - 1 do begin
b2value := readComponent(sindex);
for vindex := 0 to 1 do begin
operands[vindex] := writer.&set(fasmNums[vindex]).writeByte(b2value[vindex]).get();
end;
for vindex := 2 to 15 do begin
operands[vindex] := writer.&set(fasmNums[vindex]).writeDecimal(0).get();
end;
output.printlnInstruction('db', operands, 0, 16);
end;
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.decreaseMargin();
output.printlnHeader('; </fold>');
end;
begin
output.println();
{ -------------------------------------------------------------------------------------------------------------------------------- }
commdata[0] := CoAnsiString.create('byte4');
output.printHeader('; <fold ');
output.print(AnsiString.format(commstring, commdata));
output.println('>');
output.increaseMargin();
{ -------------------------------------------------------------------------------------------------------------------------------- }
operands[0] := 'b4';
operands[1] := writer.&set(operandA).writeByte($10).get();
output.printlnInstruction('cons', operands, 0, 2);
{ -------------------------------------------------------------------------------------------------------------------------------- }
with fldByte4Storage do for sindex := 0 to getLength() - 1 do begin
b4value := readComponent(sindex);
for vindex := 0 to 3 do begin
operands[vindex] := writer.&set(fasmNums[vindex]).writeByte(b4value[vindex]).get();
end;
for vindex := 4 to 15 do begin
operands[vindex] := writer.&set(fasmNums[vindex]).writeDecimal(0).get();
end;
output.printlnInstruction('db', operands, 0, 16);
end;
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.decreaseMargin();
output.printlnHeader('; </fold>');
end;
begin
output.println();
{ -------------------------------------------------------------------------------------------------------------------------------- }
commdata[0] := CoAnsiString.create('byte8');
output.printHeader('; <fold ');
output.print(AnsiString.format(commstring, commdata));
output.println('>');
output.increaseMargin();
{ -------------------------------------------------------------------------------------------------------------------------------- }
operands[0] := 'b8';
operands[1] := writer.&set(operandA).writeByte($10).get();
output.printlnInstruction('cons', operands, 0, 2);
{ -------------------------------------------------------------------------------------------------------------------------------- }
with fldByte8Storage do for sindex := 0 to getLength() - 1 do begin
b8value := readComponent(sindex);
for vindex := 0 to 7 do begin
operands[vindex] := writer.&set(fasmNums[vindex]).writeByte(b8value[vindex]).get();
end;
for vindex := 8 to 15 do begin
operands[vindex] := writer.&set(fasmNums[vindex]).writeDecimal(0).get();
end;
output.printlnInstruction('db', operands, 0, 16);
end;
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.decreaseMargin();
output.printlnHeader('; </fold>');
end;
begin
output.println();
{ -------------------------------------------------------------------------------------------------------------------------------- }
commdata[0] := CoAnsiString.create('short2');
output.printHeader('; <fold ');
output.print(AnsiString.format(commstring, commdata));
output.println('>');
output.increaseMargin();
{ -------------------------------------------------------------------------------------------------------------------------------- }
operands[0] := 's2';
operands[1] := writer.&set(operandA).writeByte($10).get();
output.printlnInstruction('cons', operands, 0, 2);
{ -------------------------------------------------------------------------------------------------------------------------------- }
with fldShort2Storage do for sindex := 0 to getLength() - 1 do begin
s2value := readComponent(sindex);
for vindex := 0 to 1 do begin
operands[vindex] := writer.&set(fasmNums[vindex]).writeShort(s2value[vindex]).get();
end;
for vindex := 2 to 7 do begin
operands[vindex] := writer.&set(fasmNums[vindex]).writeDecimal(0).get();
end;
output.printlnInstruction('dw', operands, 0, 8);
end;
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.decreaseMargin();
output.printlnHeader('; </fold>');
end;
begin
output.println();
{ -------------------------------------------------------------------------------------------------------------------------------- }
commdata[0] := CoAnsiString.create('short4');
output.printHeader('; <fold ');
output.print(AnsiString.format(commstring, commdata));
output.println('>');
output.increaseMargin();
{ -------------------------------------------------------------------------------------------------------------------------------- }
operands[0] := 's4';
operands[1] := writer.&set(operandA).writeByte($10).get();
output.printlnInstruction('cons', operands, 0, 2);
{ -------------------------------------------------------------------------------------------------------------------------------- }
with fldShort4Storage do for sindex := 0 to getLength() - 1 do begin
s4value := readComponent(sindex);
for vindex := 0 to 3 do begin
operands[vindex] := writer.&set(fasmNums[vindex]).writeShort(s4value[vindex]).get();
end;
for vindex := 4 to 7 do begin
operands[vindex] := writer.&set(fasmNums[vindex]).writeDecimal(0).get();
end;
output.printlnInstruction('dw', operands, 0, 8);
end;
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.decreaseMargin();
output.printlnHeader('; </fold>');
end;
begin
output.println();
{ -------------------------------------------------------------------------------------------------------------------------------- }
commdata[0] := CoAnsiString.create('short8');
output.printHeader('; <fold ');
output.print(AnsiString.format(commstring, commdata));
output.println('>');
output.increaseMargin();
{ -------------------------------------------------------------------------------------------------------------------------------- }
operands[0] := 's8';
operands[1] := writer.&set(operandA).writeByte($10).get();
output.printlnInstruction('cons', operands, 0, 2);
{ -------------------------------------------------------------------------------------------------------------------------------- }
with fldShort8Storage do for sindex := 0 to getLength() - 1 do begin
s8value := readComponent(sindex);
for vindex := 0 to 7 do begin
operands[vindex] := writer.&set(fasmNums[vindex]).writeShort(s8value[vindex]).get();
end;
output.printlnInstruction('dw', operands, 0, 8);
end;
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.decreaseMargin();
output.printlnHeader('; </fold>');
end;
begin
output.println();
{ -------------------------------------------------------------------------------------------------------------------------------- }
commdata[0] := CoAnsiString.create('int2');
output.printHeader('; <fold ');
output.print(AnsiString.format(commstring, commdata));
output.println('>');
output.increaseMargin();
{ -------------------------------------------------------------------------------------------------------------------------------- }
operands[0] := 'i2';
operands[1] := writer.&set(operandA).writeByte($10).get();
output.printlnInstruction('cons', operands, 0, 2);
{ -------------------------------------------------------------------------------------------------------------------------------- }
with fldInt2Storage do for sindex := 0 to getLength() - 1 do begin
i2value := readComponent(sindex);
for vindex := 0 to 1 do begin
operands[vindex] := writer.&set(fasmNums[vindex]).writeInt(i2value[vindex]).get();
end;
for vindex := 2 to 3 do begin
operands[vindex] := writer.&set(fasmNums[vindex]).writeDecimal(0).get();
end;
output.printlnInstruction('dd', operands, 0, 4);
end;
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.decreaseMargin();
output.printlnHeader('; </fold>');
end;
begin
output.println();
{ -------------------------------------------------------------------------------------------------------------------------------- }
commdata[0] := CoAnsiString.create('int4');
output.printHeader('; <fold ');
output.print(AnsiString.format(commstring, commdata));
output.println('>');
output.increaseMargin();
{ -------------------------------------------------------------------------------------------------------------------------------- }
operands[0] := 'i4';
operands[1] := writer.&set(operandA).writeByte($10).get();
output.printlnInstruction('cons', operands, 0, 2);
{ -------------------------------------------------------------------------------------------------------------------------------- }
with fldInt4Storage do for sindex := 0 to getLength() - 1 do begin
i4value := readComponent(sindex);
for vindex := 0 to 3 do begin
operands[vindex] := writer.&set(fasmNums[vindex]).writeInt(i4value[vindex]).get();
end;
output.printlnInstruction('dd', operands, 0, 4);
end;
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.decreaseMargin();
output.printlnHeader('; </fold>');
end;
begin
output.println();
{ -------------------------------------------------------------------------------------------------------------------------------- }
commdata[0] := CoAnsiString.create('int8');
output.printHeader('; <fold ');
output.print(AnsiString.format(commstring, commdata));
output.println('>');
output.increaseMargin();
{ -------------------------------------------------------------------------------------------------------------------------------- }
operands[0] := 'i8';
operands[1] := writer.&set(operandA).writeByte($20).get();
output.printlnInstruction('cons', operands, 0, 2);
{ -------------------------------------------------------------------------------------------------------------------------------- }
with fldInt8Storage do for sindex := 0 to getLength() - 1 do begin
i8value := readComponent(sindex);
for vindex := 0 to 7 do begin
operands[vindex] := writer.&set(fasmNums[vindex]).writeInt(i8value[vindex]).get();
end;
output.printlnInstruction('dd', operands, 0, 8);
end;
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.decreaseMargin();
output.printlnHeader('; </fold>');
end;
begin
output.println();
{ -------------------------------------------------------------------------------------------------------------------------------- }
commdata[0] := CoAnsiString.create('long');
output.printHeader('; <fold ');
output.print(AnsiString.format(commstring, commdata));
output.println('>');
output.increaseMargin();
{ -------------------------------------------------------------------------------------------------------------------------------- }
operands[0] := 'l';
operands[1] := writer.&set(operandA).writeByte($08).get();
output.printlnInstruction('cons', operands, 0, 2);
{ -------------------------------------------------------------------------------------------------------------------------------- }
with fldLongStorage do for sindex := 0 to getLength() - 1 do begin
begin
operands[0] := writer.&set(fasmNums[0]).writeLong(readComponent(sindex)).get();
end;
output.printlnInstruction('dq', operands, 0, 1);
end;
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.decreaseMargin();
output.printlnHeader('; </fold>');
end;
begin
output.println();
{ -------------------------------------------------------------------------------------------------------------------------------- }
commdata[0] := CoAnsiString.create('long2');
output.printHeader('; <fold ');
output.print(AnsiString.format(commstring, commdata));
output.println('>');
output.increaseMargin();
{ -------------------------------------------------------------------------------------------------------------------------------- }
operands[0] := 'l2';
operands[1] := writer.&set(operandA).writeByte($10).get();
output.printlnInstruction('cons', operands, 0, 2);
{ -------------------------------------------------------------------------------------------------------------------------------- }
with fldLong2Storage do for sindex := 0 to getLength() - 1 do begin
l2value := readComponent(sindex);
for vindex := 0 to 1 do begin
operands[vindex] := writer.&set(fasmNums[vindex]).writeLong(l2value[vindex]).get();
end;
output.printlnInstruction('dq', operands, 0, 2);
end;
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.decreaseMargin();
output.printlnHeader('; </fold>');
end;
begin
output.println();
{ -------------------------------------------------------------------------------------------------------------------------------- }
commdata[0] := CoAnsiString.create('long4');
output.printHeader('; <fold ');
output.print(AnsiString.format(commstring, commdata));
output.println('>');
output.increaseMargin();
{ -------------------------------------------------------------------------------------------------------------------------------- }
operands[0] := 'l4';
operands[1] := writer.&set(operandA).writeByte($20).get();
output.printlnInstruction('cons', operands, 0, 2);
{ -------------------------------------------------------------------------------------------------------------------------------- }
with fldLong4Storage do for sindex := 0 to getLength() - 1 do begin
l4value := readComponent(sindex);
for vindex := 0 to 3 do begin
operands[vindex] := writer.&set(fasmNums[vindex]).writeLong(l4value[vindex]).get();
end;
output.printlnInstruction('dq', operands, 0, 4);
end;
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.decreaseMargin();
output.printlnHeader('; </fold>');
end;
begin
output.println();
{ -------------------------------------------------------------------------------------------------------------------------------- }
commdata[0] := CoAnsiString.create('long8');
output.printHeader('; <fold ');
output.print(AnsiString.format(commstring, commdata));
output.println('>');
output.increaseMargin();
{ -------------------------------------------------------------------------------------------------------------------------------- }
operands[0] := 'l8';
operands[1] := writer.&set(operandA).writeByte($40).get();
output.printlnInstruction('cons', operands, 0, 2);
{ -------------------------------------------------------------------------------------------------------------------------------- }
with fldLong8Storage do for sindex := 0 to getLength() - 1 do begin
l8value := readComponent(sindex);
for vindex := 0 to 7 do begin
operands[vindex] := writer.&set(fasmNums[vindex]).writeLong(l8value[vindex]).get();
end;
output.printlnInstruction('dq', operands, 0, 8);
end;
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.decreaseMargin();
output.printlnHeader('; </fold>');
end;
begin
output.println();
{ -------------------------------------------------------------------------------------------------------------------------------- }
commdata[0] := CoAnsiString.create(PACKNAME_LANG + '.' + TYPENAME_STRING);
output.printHeader('; <fold ');
output.print(AnsiString.format(commstring, commdata));
output.println('>');
output.increaseMargin();
{ -------------------------------------------------------------------------------------------------------------------------------- }
operands[0] := 's';
operands[1] := writer.&set(operandA).writeByte($04).get();
output.printlnInstruction('cons', operands, 0, 2);
{ -------------------------------------------------------------------------------------------------------------------------------- }
with fldStringStorage do begin
slimit := getLength() - 1;
for sindex := 0 to slimit do begin
slower := sindex and 7;
begin
operands[slower] := writer.&set(fasmNums[slower]).writeString('-cons$s+').writeLabel(sindex).get();
end;
inc(slower);
if (slower = 8) or (sindex = slimit) then begin
output.printlnInstruction('dd', operands, 0, slower);
end;
end;
chars := &Array.newUChar1d($ffff);
for sindex := 0 to slimit do begin
stvalue := readComponent(sindex);
vlength := stvalue.length;
if vlength > $ffff then begin
raise IndexOutOfBoundsException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.generator.UNIT_NAME, 'not-encodable.too-long-string'));
end;
stvalue.getChars(1, vlength + 1, chars, 0);
output.printLabel(writer.&set(operandA).writeLabel(sindex).get());
vlimit := vlength - 1;
for vindex := -1 to vlimit do begin
vlower := (vindex + 1) and $0f;
if vindex < 0 then begin
operands[vlower] := writer.&set(fasmNums[vlower]).writeShort(vlength).get();
end else begin
operands[vlower] := writer.&set(fasmNums[vlower]).writeShort(int(chars[vindex])).get();
end;
inc(vlower);
if (vlower = $10) or (vindex = vlimit) then begin
output.printlnInstruction('dw', operands, 0, vlower);
end;
end;
end;
end;
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.decreaseMargin();
output.printlnHeader('; </fold>');
end;
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.decreaseMargin();
output.printlnHeader('; </fold>');
end;
procedure AssemblerSourceGenerator.generateDebugInfoEntries(output: AssemblerSourcePrintStream);
var
index: int;
length: int;
mindex: int;
pindex: int;
tindex: int;
nlength: int;
name: AnsiString;
mnemonic: AnsiString;
classFullName: AnsiString;
methodFullName: AnsiString;
operandA: char_Array1d;
operandB: char_Array1d;
operandC: char_Array1d;
operands: AnsiString_Array1d;
__code: Code;
__type: &Type;
__pack: Package;
lines: IntArray;
__member: Member;
__method: Callable;
__packages: PackageArray;
strings: AnsiStringStorage;
sources: UnicodeStringStorage;
__clas: ru.malik.elaborarer.avtoo.lang.ClassType;
writer: AssemblerElementWriter;
begin
writer := getAssemblerElementWriter();
operandA := &Array.newChar1d($0020);
operandB := &Array.newChar1d($0100);
operandC := &Array.newChar1d($0020);
operands := &Array.newAnsiString1d(5);
sources := fldDebugInfoSources;
strings := fldDebugInfoStrings;
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.println();
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.printHeader('; <fold ');
output.print(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.generator.UNIT_NAME, 'comment.debug.entries'));
output.println('>');
output.increaseMargin();
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.printlnInstruction('align_d', writer.&set(operandA).writeByte($20).get());
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.printlnLabel('dbgi$ient');
{ -------------------------------------------------------------------------------------------------------------------------------- }
__packages := packages;
for pindex := 0 to __packages.getLength() - 1 do begin
__pack := __packages.readComponent(pindex);
for tindex := 0 to __pack.getLength() - 1 do begin
__type := __pack.readComponent(tindex);
if not(__type is ru.malik.elaborarer.avtoo.lang.ClassType) or not __type.isCompilable() then continue;
__clas := ru.malik.elaborarer.avtoo.lang.ClassType(__type);
classFullName := __clas.fasmFullName;
for mindex := 0 to __clas.getLength() - 1 do begin
__member := __clas.readComponent(mindex);
if not(__member is Callable) or __member.isAbstract() then continue;
__method := Callable(__member);
mnemonic := 'dientry';
name := __method.specialSimpleName;
methodFullName := __method.fasmFullName;
nlength := name.length;
strings.indexAcquire(name);
if (nlength > 1) and (name[1] = '<') and (name[nlength] = '>') then begin
mnemonic := 'dientry_s';
name := name.substring(2, nlength);
end;
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.printHeader('if(used ');
output.print(methodFullName);
output.print(') ; <fold ');
output.print(__method.toString());
output.println('>');
output.increaseMargin();
{ -------------------------------------------------------------------------------------------------------------------------------- }
operands[0] := writer.&set(operandA).writeLabel(sources.indexAcquire(__clas.textSourcePath)).get();
operands[1] := classFullName;
operands[2] := name;
operands[3] := methodFullName;
operands[4] := '\';
output.printlnInstruction(mnemonic, operands, 0, 5);
{ -------------------------------------------------------------------------------------------------------------------------------- }
__code := __method.code;
lines := nil;
length := 0;
if __code <> nil then begin
lines := __code.debugLineIndices;
length := lines.getLength();
end;
if length <= 0 then begin
operands[0] := writer.&set(operandA).writeDecimal(0).get();
operands[1] := '';
operands[2] := '.D.IEND';
output.printlnContinuation(operands, 0, 3);
end else begin
operands[3] := '\';
index := 0;
repeat
operands[0] := writer.&set(operandA).writeDecimal(lines.readComponent(index) + 1).get();
operands[1] := writer.&set(operandB).writeLabel('D', index).get();
inc(index);
if index >= length then begin
operands[2] := '.D.IEND';
output.printlnContinuation(operands, 0, 3);
break;
end;
operands[2] := writer.&set(operandC).writeLabel('D', index).get();
output.printlnContinuation(operands, 0, 4);
until false;
end;
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.decreaseMargin();
output.printlnHeader('end if ; </fold>');
end;
end;
end;
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.printlnLabel('.$iend$');
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.decreaseMargin();
output.printlnHeader('; </fold>');
end;
procedure AssemblerSourceGenerator.generateDebugInfoSources(output: AssemblerSourcePrintStream);
var
index: int;
nlimit: int;
nlower: int;
nindex: int;
nlength: int;
name: UnicodeString;
chars: uchar_Array1d;
operandA: char_Array1d;
fasmNums: char_Array2d;
operands: AnsiString_Array1d;
sources: UnicodeStringStorage;
writer: AssemblerElementWriter;
begin
writer := getAssemblerElementWriter();
operandA := &Array.newChar1d($0020);
fasmNums := &Array.newChar2d($0010, $0020);
operands := &Array.newAnsiString1d($10);
sources := fldDebugInfoSources;
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.println();
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.printHeader('; <fold ');
output.print(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.generator.UNIT_NAME, 'comment.debug.sources'));
output.println('>');
output.increaseMargin();
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.printlnInstruction('align_d', writer.&set(operandA).writeByte($10).get());
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.printLabel('dbgi$isrc');
{ -------------------------------------------------------------------------------------------------------------------------------- }
chars := &Array.newUChar1d($ffff);
for index := 0 to sources.getLength() - 1 do begin
name := sources.readComponent(index);
nlength := name.length;
if nlength > $ffff then nlength := $ffff;
name.getChars(1, nlength + 1, chars, 0);
output.printLabel(writer.&set(operandA).writeLabel(index).get());
nlimit := nlength - 1;
for nindex := -1 to nlimit do begin
nlower := (nindex + 1) and $0f;
if nindex < 0 then begin
operands[nlower] := writer.&set(fasmNums[nlower]).writeShort(nlength).get();
end else begin
operands[nlower] := writer.&set(fasmNums[nlower]).writeShort(int(chars[nindex])).get();
end;
inc(nlower);
if (nlower = $10) or (nindex = nlimit) then begin
output.printlnInstruction('dw', operands, 0, nlower);
end;
end;
end;
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.printlnLabel('.$iend$');
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.decreaseMargin();
output.printlnHeader('; </fold>');
end;
procedure AssemblerSourceGenerator.generateDebugInfoStrings(output: AssemblerSourcePrintStream);
var
index: int;
nlength: int;
name: AnsiString;
mnemonic: AnsiString;
operandA: char_Array1d;
strings: AnsiStringStorage;
writer: AssemblerElementWriter;
begin
writer := getAssemblerElementWriter();
operandA := &Array.newChar1d($0100);
strings := fldDebugInfoStrings;
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.println();
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.printHeader('; <fold ');
output.print(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.generator.UNIT_NAME, 'comment.debug.strings'));
output.println('>');
output.increaseMargin();
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.printlnInstruction('align_d', writer.&set(operandA).writeByte($10).get());
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.printLabel('dbgi$istr');
{ -------------------------------------------------------------------------------------------------------------------------------- }
for index := 0 to strings.getLength() - 1 do begin
name := strings.readComponent(index);
nlength := name.length;
if (nlength > 1) and (name[1] = '<') and (name[nlength] = '>') then begin
mnemonic := 'distring_s';
name := name.substring(2, nlength);
end else begin
mnemonic := 'distring';
end;
output.printlnInstruction(mnemonic, name);
end;
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.printlnLabel('.$iend$');
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.decreaseMargin();
output.printlnHeader('; </fold>');
end;
procedure AssemblerSourceGenerator.generateProgramme(output: AssemblerSourcePrintStream);
var
index: int;
pindex: int;
tindex: int;
plength: int;
codeLength: int;
pathLength: int;
name: UnicodeString;
path: UnicodeString;
operandA: char_Array1d;
operandB: char_Array1d;
operands: AnsiString_Array1d;
__type: &Type;
__pack: Package;
__packages: PackageArray;
resourcesTable: HashtableOfUnicodeStringToResourceLocation;
writer: AssemblerElementWriter;
begin
writer := getAssemblerElementWriter();
operandA := &Array.newChar1d($ffff);
operandB := &Array.newChar1d($ffff);
operands := &Array.newAnsiString1d(2);
__packages := packages;
resourcesTable := fldResourcesTable;
plength := __packages.getLength();
begin
output.println();
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.printHeader('; <fold ');
output.print(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.generator.UNIT_NAME, 'comment.header'));
output.println('>');
output.increaseMargin();
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.printlnInstruction('include', '"!format/!header.inc"');
output.printlnInstruction('include', '"!macro/!main.inc"');
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.decreaseMargin();
output.printlnHeader('; </fold>');
end;
begin
output.println();
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.printHeader('; <fold ');
output.print(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.generator.UNIT_NAME, 'comment.code'));
output.println('>');
output.increaseMargin();
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.printlnInstruction('include', '"!format/chapter/code.inc"');
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.printLabel('code$begin');
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.printlnInstruction('include', '"!proc/!main.inc"');
output.printlnInstruction('include', '"!inst/!main.inc"');
{ -------------------------------------------------------------------------------------------------------------------------------- }
codeLength := writer.&set(operandA).writeString('"code/').offset;
for pindex := 0 to plength - 1 do begin
__pack := __packages.readComponent(pindex);
pathLength := writer.&set(operandA, codeLength).writeString(__pack.fasmFullName).writeChar('/').offset;
for tindex := 0 to __pack.getLength() - 1 do begin
__type := __pack.readComponent(tindex);
if
(__type is ru.malik.elaborarer.avtoo.lang.ClassType) and
(not(__type is ArrayType) or not ru.malik.elaborarer.avtoo.lang.ClassType(__type).getSuperclassType().isArray())
then begin
output.printlnInstruction('include', writer.&set(operandA, pathLength).writeString(__type.fasmFileName.toUTF8()).writeString('.inc"').get());
end;
end;
end;
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.printlnLabel('code$end');
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.decreaseMargin();
output.printlnHeader('; </fold>');
end;
begin
output.println();
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.printHeader('; <fold ');
output.print(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.generator.UNIT_NAME, 'comment.data'));
output.println('>');
output.increaseMargin();
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.printlnInstruction('include', '"!format/chapter/data.inc"');
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.printLabel('data$begin');
{ -------------------------------------------------------------------------------------------------------------------------------- }
codeLength := writer.&set(operandA).writeString('"data/').offset;
for pindex := 0 to plength - 1 do begin
__pack := __packages.readComponent(pindex);
pathLength := writer.&set(operandA, codeLength).writeString(__pack.fasmFullName).writeChar('/').offset;
output.printlnInstruction('include', writer.&set(operandA, pathLength).writeString('!package.inc"').get());
for tindex := 0 to __pack.getLength() - 1 do begin
__type := __pack.readComponent(tindex);
if __type.isCompilable() then begin
output.printlnInstruction('include', writer.&set(operandA, pathLength).writeString(__type.fasmFileName.toUTF8()).writeString('.inc"').get());
end;
end;
end;
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.printlnLabel('data$end');
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.decreaseMargin();
output.printlnHeader('; </fold>');
end;
begin
output.println();
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.printHeader('; <fold ');
output.print(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.generator.UNIT_NAME, 'comment.constants'));
output.println('>');
output.increaseMargin();
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.printlnInstruction('include', '"!format/chapter/const.inc"');
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.printLabel('cons$begin');
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.printlnInstruction('include', '"const/proc.inc"');
output.printlnInstruction('include', '"const/inst.inc"');
output.printlnInstruction('include', '"const/prog.inc"');
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.printlnLabel('cons$end');
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.decreaseMargin();
output.printlnHeader('; </fold>');
end;
begin
output.println();
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.printHeader('; <fold ');
output.print(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.generator.UNIT_NAME, 'comment.resources'));
output.println('>');
output.increaseMargin();
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.printlnInstruction('include', '"!format/chapter/rsrc.inc"');
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.printLabel('rsrc$begin');
{ -------------------------------------------------------------------------------------------------------------------------------- }
for index := 0 to resourcesTable.length - 1 do begin
name := resourcesTable.keyAt(index);
path := resourcesTable[name].destinationPath;
operands[0] := writer.&set(operandA).writeChar('"').writeString(path.toUTF8()).writeChar('"').get();
operands[1] := writer.&set(operandB).writeChar('"').writeString(name.toUTF8()).writeChar('"').get();
output.printlnInstruction('avtrsrc', operands, 0, 2);
end;
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.printlnLabel('rsrc$end');
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.decreaseMargin();
output.printlnHeader('; </fold>');
end;
begin
output.println();
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.printHeader('; <fold ');
output.print(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.generator.UNIT_NAME, 'comment.debug'));
output.println('>');
output.increaseMargin();
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.printlnInstruction('include', '"!format/chapter/dbgi.inc"');
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.printLabel('dbgi$begin');
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.printlnInstruction('dbinfob', '"AVTC 0.5 [2022-08-04]"');
output.printlnInstruction('include', '"dbgi/strings.inc"');
output.printlnInstruction('include', '"dbgi/sources.inc"');
output.printlnInstruction('include', '"dbgi/entries.inc"');
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.printlnLabel('dbgi$end');
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.decreaseMargin();
output.printlnHeader('; </fold>');
end;
begin
output.println();
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.printHeader('; <fold ');
output.print(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.generator.UNIT_NAME, 'comment.footer'));
output.println('>');
output.increaseMargin();
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.printlnInstruction('include', '"!format/!footer.inc"');
{ -------------------------------------------------------------------------------------------------------------------------------- }
output.decreaseMargin();
output.printlnHeader('; </fold>');
end;
end;
function AssemblerSourceGenerator.newAssemblerElementWriter(): AssemblerElementWriter;
begin
result := nil;
end;
function AssemblerSourceGenerator.newAssemblerSourcePrintStream(): AssemblerSourcePrintStream;
begin
result := nil;
end;
function AssemblerSourceGenerator.getOverwritten(): UnicodeString;
begin
result := fldOverwritten;
end;
function AssemblerSourceGenerator.getAssemblerElementWriter(): AssemblerElementWriter;
begin
result := fldGlobalWriter;
end;
constructor AssemblerSourceGenerator.create(__reflect: boolean; const __destinationName: UnicodeString);
begin
inherited create(false);
fldReflect := __reflect;
fldDestinationName := __destinationName;
fldSourcesTable := HashtableOfUnicodeStringToLibrary.create();
fldRealStorage := RealStorage.create();
fldDoubleStorage := DoubleStorage.create();
fldDouble2Storage := Double2Storage.create();
fldDouble4Storage := Double4Storage.create();
fldDouble8Storage := Double8Storage.create();
fldFloatStorage := FloatStorage.create();
fldFloat2Storage := Float2Storage.create();
fldFloat4Storage := Float4Storage.create();
fldFloat8Storage := Float8Storage.create();
fldByte2Storage := Byte2Storage.create();
fldByte4Storage := Byte4Storage.create();
fldByte8Storage := Byte8Storage.create();
fldShort2Storage := Short2Storage.create();
fldShort4Storage := Short4Storage.create();
fldShort8Storage := Short8Storage.create();
fldInt2Storage := Int2Storage.create();
fldInt4Storage := Int4Storage.create();
fldInt8Storage := Int8Storage.create();
fldLongStorage := LongStorage.create();
fldLong2Storage := Long2Storage.create();
fldLong4Storage := Long4Storage.create();
fldLong8Storage := Long8Storage.create();
fldStringStorage := UnicodeStringStorage.create();
fldDebugInfoSources := UnicodeStringStorage.create();
fldDebugInfoStrings := AnsiStringStorage.create();
fldResourcesTable := HashtableOfUnicodeStringToResourceLocation.create();
end;
destructor AssemblerSourceGenerator.destroy;
begin
fldSourcesTable.free();
fldRealStorage.free();
fldDoubleStorage.free();
fldDouble2Storage.free();
fldDouble4Storage.free();
fldDouble8Storage.free();
fldFloatStorage.free();
fldFloat2Storage.free();
fldFloat4Storage.free();
fldFloat8Storage.free();
fldByte2Storage.free();
fldByte4Storage.free();
fldByte8Storage.free();
fldShort2Storage.free();
fldShort4Storage.free();
fldShort8Storage.free();
fldInt2Storage.free();
fldInt4Storage.free();
fldInt8Storage.free();
fldLongStorage.free();
fldLong2Storage.free();
fldLong4Storage.free();
fldLong8Storage.free();
fldStringStorage.free();
fldDebugInfoSources.free();
fldDebugInfoStrings.free();
freeResourcesTable(fldResourcesTable);
inherited destroy;
end;
procedure AssemblerSourceGenerator.afterConstruction();
var
writer: AssemblerElementWriter;
begin
inherited afterConstruction();
writer := newAssemblerElementWriter();
if writer = nil then writer := AssemblerElementWriter.create();
fldGlobalWriter := writer;
end;
procedure AssemblerSourceGenerator.beforeDestruction();
begin
fldGlobalWriter.free();
inherited beforeDestruction();
end;
procedure AssemblerSourceGenerator.compile();
var
index: int;
boundA: int;
boundB: int;
aindex: int;
lindex: int;
mindex: int;
pindex: int;
tindex: int;
blength: int;
plength: int;
name: UnicodeString;
codePath: UnicodeString;
dataPath: UnicodeString;
__destinationName: UnicodeString;
__destinationPath: UnicodeString;
writerRelativePath: UnicodeString;
readerRelativePath: UnicodeString;
path: uchar_Array1d;
buffer: byte_Array1d;
__type: &Type;
__pack: Package;
__next: Package;
__member: Member;
reader: ByteReader;
writer: ByteWriter;
__method: Callable;
__project: ru.malik.elaborarer.avtoo.lang.&Library;
__library: ru.malik.elaborarer.avtoo.lang.&Library;
__fileSystem: FileSystem;
__packages: PackageArray;
__classes: ClassTypeArray;
__libraries: LibraryArray;
location: ResourceLocation;
output: AssemblerSourcePrintStream;
sourcesTable: HashtableOfUnicodeStringToLibrary;
__clas: ru.malik.elaborarer.avtoo.lang.ClassType;
resourcesTable: HashtableOfUnicodeStringToResourceLocation;
begin
{ -- предыдущие стадии -- }
inherited compile();
{ 8. Стадия выгрузки данных }
__libraries := libraries;
for lindex := 0 to __libraries.getLength() - 1 do begin
__library := __libraries.readComponent(lindex);
findSourcesIn(__library);
findResourcesIn(__library);
end;
if fldReflect then begin
__classes := classes;
for tindex := __classes.getLength() - 1 downto 0 do begin
__clas := __classes.readComponent(tindex);
if __clas.isCompilable() then for mindex := __clas.getLength() - 1 downto 0 do begin
__member := __clas.readComponent(mindex);
if not __member.isStatic() then begin
if __member is Field then begin
Field(__member).&type.makeCompilable();
continue;
end;
if __member is Callable then begin
__method := Callable(__member);
__method.&type.makeCompilable();
with __method.arguments do for aindex := getLength() - 1 downto 0 do readComponent(aindex).&type.makeCompilable();
end;
end;
end;
end;
end;
buffer := &Array.newByte1d(COPY_BUFFER_LENGTH);
__destinationName := fldDestinationName;
if __destinationName = '' then begin
__destinationName := PROGRAMME_DESTINATION_PATH;
end else begin
__destinationName := (PROGRAMME_DESTINATION_PATH + '.') + __destinationName;
end;
__project := project;
__fileSystem := __project.fileSystem;
__destinationPath := prepareDestinationPath(__fileSystem, __project.directoryPath + __destinationName);
fldOverwritten := __destinationPath;
sourcesTable := fldSourcesTable;
for index := 0 to sourcesTable.length - 1 do begin
writerRelativePath := sourcesTable.keyAt(index);
readerRelativePath := (ASSEMBLER_SOURCE_PATH + '/') + writerRelativePath;
__library := sourcesTable[writerRelativePath];
createImmediateDirectories(__fileSystem, __destinationPath, writerRelativePath);
reader := __library.fileSystem.openFileForRead(__library.directoryPath + readerRelativePath);
try
writer := __fileSystem.createFile(__destinationPath + writerRelativePath);
try
repeat
blength := reader.read(buffer);
if blength > 0 then writer.write(buffer, 0, blength);
until blength < COPY_BUFFER_LENGTH;
writer.flush();
finally
writer.close();
end;
finally
reader.close();
end;
end;
resourcesTable := fldResourcesTable;
for index := 0 to resourcesTable.length - 1 do begin
location := resourcesTable[resourcesTable.keyAt(index)];
readerRelativePath := location.relativePath;
__library := location.&library;
path := ('rsrc' + readerRelativePath.substring(readerRelativePath.indexOf('/'))).toUCharArray();
boundA := &Array.indexOf('/', path, 0, 0);
boundB := &Array.lastIndexOf('/', path, CoInt.MAX_VALUE, 0);
pindex := boundA;
repeat
pindex := &Array.indexOf('/', path, pindex + 1, 0);
if (pindex <= boundA) or (pindex >= boundB) then break;
path[pindex] := '.';
until false;
writerRelativePath := UnicodeString.create(path);
location.destinationPath := writerRelativePath;
createImmediateDirectories(__fileSystem, __destinationPath, writerRelativePath);
reader := __library.fileSystem.openFileForRead(__library.directoryPath + readerRelativePath);
try
writer := __fileSystem.createFile(__destinationPath + writerRelativePath);
try
repeat
blength := reader.read(buffer);
if blength > 0 then writer.write(buffer, 0, blength);
until blength < COPY_BUFFER_LENGTH;
writer.flush();
finally
writer.close();
end;
finally
reader.close();
end;
end;
__fileSystem.createDirectory(__destinationPath + 'code');
__fileSystem.createDirectory(__destinationPath + 'data');
output := newAssemblerSourcePrintStream();
if output = nil then begin
output := AssemblerSourcePrintStream.create();
end;
try
with output as DataEncoder do begin
__packages := packages;
plength := __packages.getLength();
__pack := nil;
if plength > 0 then begin
__pack := __packages.readComponent(0);
end;
pindex := 0;
while pindex < plength do begin
inc(pindex);
if pindex >= plength then begin
__next := nil;
end else begin
__next := __packages.readComponent(pindex);
end;
name := __pack.fasmFileName;
codePath := __destinationPath + 'code/' + name + '/';
dataPath := __destinationPath + 'data/' + name + '/';
__fileSystem.createDirectory(codePath.substring(1, codePath.length));
__fileSystem.createDirectory(dataPath.substring(1, dataPath.length));
begin
generatePackageData(__pack, __next, output);
writer := __fileSystem.createFile(dataPath + '!package.inc');
try
saveToOutputStream(writer);
writer.flush();
finally
writer.close();
end;
clear();
end;
for tindex := 0 to __pack.getLength() - 1 do begin
__type := __pack.readComponent(tindex);
if __type is PrimitiveType then begin
generatePrimitiveData(PrimitiveType(__type), output);
writer := __fileSystem.createFile(dataPath + __type.fasmFileName + '.inc');
try
saveToOutputStream(writer);
writer.flush();
finally
writer.close();
end;
clear();
continue;
end;
if (__type is ru.malik.elaborarer.avtoo.lang.ClassType) and __type.isCompilable() then begin
__clas := ru.malik.elaborarer.avtoo.lang.ClassType(__type);
begin
generateClassData(__clas, output);
writer := __fileSystem.createFile(dataPath + __type.fasmFileName + '.inc');
try
saveToOutputStream(writer);
writer.flush();
finally
writer.close();
end;
clear();
end;
if not(__clas is ArrayType) or not __clas.getSuperclassType().isArray() then begin
generateClassCode(__clas, output);
writer := __fileSystem.createFile(codePath + __type.fasmFileName + '.inc');
try
if __clas.hasNativeCallables() then begin
__library := __pack.parentLibrary;
reader := __library.fileSystem.openFileForRead(
__library.directoryPath + (ASSEMBLER_SOURCE_PATH + '/code/') + __pack.fasmFileName + '/' + __clas.fasmFileName + '.inc'
);
try
repeat
blength := reader.read(buffer);
if blength > 0 then writer.write(buffer, 0, blength);
until blength < COPY_BUFFER_LENGTH;
finally
reader.close();
end;
end;
saveToOutputStream(writer);
writer.flush();
finally
writer.close();
end;
clear();
end;
end;
end;
__pack := __next;
end;
createImmediateDirectories(__fileSystem, __destinationPath, 'const/');
begin
generateConstants(output);
writer := __fileSystem.createFile(__destinationPath + 'const/prog.inc');
try
saveToOutputStream(writer);
writer.flush();
finally
writer.close();
end;
clear();
end;
createImmediateDirectories(__fileSystem, __destinationPath, 'dbgi/');
begin
generateDebugInfoEntries(output);
writer := __fileSystem.createFile(__destinationPath + 'dbgi/entries.inc');
try
saveToOutputStream(writer);
writer.flush();
finally
writer.close();
end;
clear();
end;
begin
generateDebugInfoSources(output);
writer := __fileSystem.createFile(__destinationPath + 'dbgi/sources.inc');
try
saveToOutputStream(writer);
writer.flush();
finally
writer.close();
end;
clear();
end;
begin
generateDebugInfoStrings(output);
writer := __fileSystem.createFile(__destinationPath + 'dbgi/strings.inc');
try
saveToOutputStream(writer);
writer.flush();
finally
writer.close();
end;
clear();
end;
begin
generateProgramme(output);
writer := __fileSystem.createFile(__destinationPath + 'programme.asm');
try
saveToOutputStream(writer);
writer.flush();
finally
writer.close();
end;
clear();
end;
end;
finally
output.free();
end;
end;
procedure AssemblerSourceGenerator.clear();
begin
fldSourcesTable.clear();
fldRealStorage.clear();
fldDoubleStorage.clear();
fldDouble2Storage.clear();
fldDouble4Storage.clear();
fldDouble8Storage.clear();
fldFloatStorage.clear();
fldFloat2Storage.clear();
fldFloat4Storage.clear();
fldFloat8Storage.clear();
fldByte2Storage.clear();
fldByte4Storage.clear();
fldByte8Storage.clear();
fldShort2Storage.clear();
fldShort4Storage.clear();
fldShort8Storage.clear();
fldInt2Storage.clear();
fldInt4Storage.clear();
fldInt8Storage.clear();
fldLongStorage.clear();
fldLong2Storage.clear();
fldLong4Storage.clear();
fldLong8Storage.clear();
fldStringStorage.clear();
fldDebugInfoSources.clear();
fldDebugInfoStrings.clear();
clearResourcesTable(fldResourcesTable);
inherited clear();
end;
{%endregion}
{%region BinarySourceGeneratorConstants }
class function BinarySourceGeneratorConstants.serializeVersion(): ByteArrayOutputStream;
var
stream: ByteArrayOutputStream;
begin
stream := ByteArrayOutputStream.create();
try
with AVTOORecompilable, DataOutputStream.create(stream), bigEndianDataOutput do try
writeInt(CHUNK_VERS);
writeInt(VERSION_AVTR);
finally
free();
end;
except
stream.free();
raise;
end;
result := stream;
end;
class function BinarySourceGeneratorConstants.serializeTextSource(source: TextSource; charset: Charset): ByteArrayOutputStream;
var
stream: ByteArrayOutputStream;
begin
stream := ByteArrayOutputStream.create();
try
with AVTOORecompilable, DataOutputStream.create(stream), bigEndianDataOutput do try
writeInt(CHUNK_SURC);
write(charset.encode(source.textSourcePath.toUCharArray()));
finally
free();
end;
except
stream.free();
raise;
end;
result := stream;
end;
class function BinarySourceGeneratorConstants.serializeEnd(): ByteArrayOutputStream;
var
stream: ByteArrayOutputStream;
begin
stream := ByteArrayOutputStream.create();
try
with AVTOORecompilable, DataOutputStream.create(stream), bigEndianDataOutput do try
writeInt(CHUNK_IEND);
finally
free();
end;
except
stream.free();
raise;
end;
result := stream;
end;
procedure BinarySourceGeneratorConstants.removeAllElements();
var
index: int;
element: TObject;
&array: TObject_Array1d;
begin
&array := fldArray;
for index := 0 to fldLength - 1 do begin
element := &array[index];
if element is RefCountObject then begin
&array[index] := nil;
element.free();
end;
end;
fldLength := 0;
end;
function BinarySourceGeneratorConstants.getOperandIndex(operandC: Constant; operandI: TableItem; thisArgument: Local): int;
begin
if operandC <> nil then begin
result := indexAcquire(operandC);
exit;
end;
if operandI = thisArgument then begin
result := 0;
exit;
end;
if operandI is Local then begin
result := indexOf(operandI.specialSimpleName);
exit;
end;
result := indexAcquire(operandI);
end;
function BinarySourceGeneratorConstants.indexOf(const item: AnsiString): int;
var
asObject: TObject;
begin
asObject := CoUnicodeString.create(item.toUTF16());
try
result := indexOf(asObject);
finally
asObject.free();
end;
end;
function BinarySourceGeneratorConstants.indexAcquire(const item: AnsiString): int;
var
isIgnored: boolean;
index: int;
asObject: TObject;
begin
isIgnored := true;
asObject := CoUnicodeString.create(item.toUTF16());
try
index := indexOf(asObject);
if index < 0 then begin
index := fldLength;
append(asObject);
isIgnored := false;
end;
finally
if isIgnored then asObject.free();
end;
result := index;
end;
function BinarySourceGeneratorConstants.indexAcquire(const item: UnicodeString): int;
var
isIgnored: boolean;
index: int;
asObject: TObject;
begin
isIgnored := true;
asObject := CoUnicodeString.create(item);
try
index := indexOf(asObject);
if index < 0 then begin
index := fldLength;
append(asObject);
isIgnored := false;
end;
finally
if isIgnored then asObject.free();
end;
result := index;
end;
function BinarySourceGeneratorConstants.indexAcquire(const item: TableItem): int;
label
break_label0;
var
index: int;
begin
index := indexOf(item);
if index < 0 then begin
begin
if item is RequiredReflectItem then with RequiredReflectItem(item) do begin
indexAcquire(recompilableName);
goto break_label0;
end;
if item is Fieldoid then with item as Member do begin
indexAcquire(parentType);
indexAcquire(recompilableName);
goto break_label0;
end;
if item is Callable then with Callable(item), arguments do begin
indexAcquire(parentType);
indexAcquire(recompilableName);
for index := 0 to getLength() - 1 do indexAcquire(readComponent(index).&type);
end;
end;
break_label0:
index := fldLength;
append(item);
end;
result := index;
end;
function BinarySourceGeneratorConstants.indexAcquire(const item: TypedMember): int;
begin
result := indexAcquire(TableItem(Lang.cast(item, TableItem)));
end;
function BinarySourceGeneratorConstants.indexAcquire(const item: Constant): int;
var
isIgnored: boolean;
index: int;
asObject: TObject;
begin
if item.isString() then begin
result := indexAcquire((item.asInterface() as Value).asUnicodeString());
exit;
end;
if item.isReference() then begin
result := indexAcquire(item.asObject() as RequiredReflectItem);
exit;
end;
isIgnored := true;
if item.isBoolean() then begin
asObject := CoBoolean.create(item.asBoolean());
end else
with AVTOOConstants do case item.&type.kind of
TYP_BYTE:
asObject := VCoByte.create(item.asLong());
TYP_BYTE2:
asObject := VCoByte2.create(item.asLong2());
TYP_BYTE4:
asObject := VCoByte4.create(item.asLong4());
TYP_BYTE8:
asObject := VCoByte8.create(item.asLong8());
TYP_SHORT:
asObject := VCoShort.create(item.asLong());
TYP_SHORT2:
asObject := VCoShort2.create(item.asLong2());
TYP_SHORT4:
asObject := VCoShort4.create(item.asLong4());
TYP_SHORT8:
asObject := VCoShort8.create(item.asLong8());
TYP_INT:
asObject := VCoInt.create(item.asLong());
TYP_INT2:
asObject := VCoInt2.create(item.asLong2());
TYP_INT4:
asObject := VCoInt4.create(item.asLong4());
TYP_INT8:
asObject := VCoInt8.create(item.asLong8());
TYP_LONG:
asObject := VCoLong.create(item.asLong());
TYP_LONG2:
asObject := VCoLong2.create(item.asLong2());
TYP_LONG4:
asObject := VCoLong4.create(item.asLong4());
TYP_LONG8:
asObject := VCoLong8.create(item.asLong8());
TYP_FLOAT:
asObject := VCoFloat.create(item.asDouble());
TYP_FLOAT2:
asObject := VCoFloat2.create(item.asDouble2());
TYP_FLOAT4:
asObject := VCoFloat4.create(item.asDouble4());
TYP_FLOAT8:
asObject := VCoFloat8.create(item.asDouble8());
TYP_DOUBLE:
asObject := VCoDouble.create(item.asDouble());
TYP_DOUBLE2:
asObject := VCoDouble2.create(item.asDouble2());
TYP_DOUBLE4:
asObject := VCoDouble4.create(item.asDouble4());
TYP_DOUBLE8:
asObject := VCoDouble8.create(item.asDouble8());
TYP_REAL:
asObject := VCoReal.create(item.asReal());
else
asObject := CoUChar.create(item.asUChar());
end;
try
index := indexOf(asObject);
if index < 0 then begin
index := fldLength;
append(asObject);
isIgnored := false;
end;
finally
if isIgnored then asObject.free();
end;
result := index;
end;
constructor BinarySourceGeneratorConstants.create();
begin
inherited create(false);
end;
destructor BinarySourceGeneratorConstants.destroy;
begin
removeAllElements();
inherited destroy;
end;
procedure BinarySourceGeneratorConstants.afterConstruction();
begin
inherited afterConstruction();
append(nil);
end;
procedure BinarySourceGeneratorConstants.clear();
begin
removeAllElements();
append(nil);
end;
function BinarySourceGeneratorConstants.serializeConstants(charset: Charset): ByteArrayOutputStream;
var
aindex: int;
eindex: int;
alength: int;
dataString: UnicodeString;
elements: TObject_Array1d;
etype: TClass;
element: TObject;
stream: ByteArrayOutputStream;
begin
stream := ByteArrayOutputStream.create();
try
with AVTOORecompilable, DataOutputStream.create(stream), bigEndianDataOutput do try
writeInt(CHUNK_CONS);
elements := fldArray;
for eindex := 1 to fldLength - 1 do begin
element := elements[eindex];
if element = nil then begin
raise UnencodableDataException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.generator.UNIT_NAME, 'not-encodable.null-pointer'));
end;
etype := element.classType();
if etype = CoBoolean then begin
writeShort(CONST_Z);
if CoBoolean(element).asBoolean() then begin
writeShort(-1);
continue;
end;
writeShort(0);
continue;
end;
if etype = CoUChar then begin
writeShort(CONST_C);
writeShort(short(CoUChar(element).asInt()));
continue;
end;
if etype = VCoByte then begin
writeShort(CONST_B);
writeShort(VCoByte(element).asByte());
continue;
end;
if etype = VCoByte2 then begin
writeShort(CONST_B2);
writeByte2(VCoByte2(element).asByte2());
continue;
end;
if etype = VCoByte4 then begin
writeShort(CONST_B4);
writeByte4(VCoByte4(element).asByte4());
continue;
end;
if etype = VCoByte8 then begin
writeShort(CONST_B8);
writeByte8(VCoByte8(element).asByte8());
continue;
end;
if etype = VCoShort then begin
writeShort(CONST_S);
writeShort(VCoShort(element).asShort());
continue;
end;
if etype = VCoShort2 then begin
writeShort(CONST_S2);
writeShort2(VCoShort2(element).asShort2());
continue;
end;
if etype = VCoShort4 then begin
writeShort(CONST_S4);
writeShort4(VCoShort4(element).asShort4());
continue;
end;
if etype = VCoShort8 then begin
writeShort(CONST_S8);
writeShort8(VCoShort8(element).asShort8());
continue;
end;
if etype = VCoInt then begin
writeShort(CONST_I);
writeInt(VCoInt(element).asInt());
continue;
end;
if etype = VCoInt2 then begin
writeShort(CONST_I2);
writeInt2(VCoInt2(element).asInt2());
continue;
end;
if etype = VCoInt4 then begin
writeShort(CONST_I4);
writeInt4(VCoInt4(element).asInt4());
continue;
end;
if etype = VCoInt8 then begin
writeShort(CONST_I8);
writeInt8(VCoInt8(element).asInt8());
continue;
end;
if etype = VCoLong then begin
writeShort(CONST_J);
writeLong(VCoLong(element).asLong());
continue;
end;
if etype = VCoLong2 then begin
writeShort(CONST_J2);
writeLong2(VCoLong2(element).asLong2());
continue;
end;
if etype = VCoLong4 then begin
writeShort(CONST_J4);
writeLong4(VCoLong4(element).asLong4());
continue;
end;
if etype = VCoLong8 then begin
writeShort(CONST_J8);
writeLong8(VCoLong8(element).asLong8());
continue;
end;
if etype = VCoFloat then begin
writeShort(CONST_F);
writeFloat(VCoFloat(element).asFloat());
continue;
end;
if etype = VCoFloat2 then begin
writeShort(CONST_F2);
writeFloat2(VCoFloat2(element).asFloat2());
continue;
end;
if etype = VCoFloat4 then begin
writeShort(CONST_F4);
writeFloat4(VCoFloat4(element).asFloat4());
continue;
end;
if etype = VCoFloat8 then begin
writeShort(CONST_F8);
writeFloat8(VCoFloat8(element).asFloat8());
continue;
end;
if etype = VCoDouble then begin
writeShort(CONST_D);
writeDouble(VCoDouble(element).asDouble());
continue;
end;
if etype = VCoDouble2 then begin
writeShort(CONST_D2);
writeDouble2(VCoDouble2(element).asDouble2());
continue;
end;
if etype = VCoDouble4 then begin
writeShort(CONST_D4);
writeDouble4(VCoDouble4(element).asDouble4());
continue;
end;
if etype = VCoDouble8 then begin
writeShort(CONST_D8);
writeDouble8(VCoDouble8(element).asDouble8());
continue;
end;
if etype = VCoReal then begin
writeShort(CONST_R);
writeReal(VCoReal(element).asReal());
continue;
end;
if etype = CoUnicodeString then begin
dataString := CoUnicodeString(element).asUnicodeString();
writeShort(CONST_ST);
writeShort(dataString.length);
write(charset.encode(dataString.toUCharArray()));
continue;
end;
if etype.inheritsFrom(Package) then with TableItem(element) do begin
writeShort(CONST_PK);
writeInt(indexOf(recompilableName));
continue;
end;
if etype.inheritsFrom(&Type) then with TableItem(element) do begin
writeShort(CONST_TP);
writeInt(indexOf(recompilableName));
continue;
end;
if etype.inheritsFrom(Field) then with Member(element) do begin
writeShort(CONST_FL);
writeInt(indexOf(parentType));
writeInt(indexOf(recompilableName));
continue;
end;
if etype.inheritsFrom(&Property) then with Member(element) do begin
writeShort(CONST_PR);
writeInt(indexOf(parentType));
writeInt(indexOf(recompilableName));
continue;
end;
if etype.inheritsFrom(Callable) then with Callable(element), arguments do begin
writeShort(CONST_CL);
writeInt(indexOf(parentType));
writeInt(indexOf(recompilableName));
alength := getLength();
writeShort(alength);
for aindex := 0 to alength - 1 do writeInt(indexOf(readComponent(aindex).&type));
continue;
end;
raise UnencodableDataException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.generator.UNIT_NAME, 'not-encodable.constant-type'), [
CoAnsiString.create(etype.className())
]))
end;
finally
free();
end;
except
stream.free();
raise;
end;
result := stream;
end;
function BinarySourceGeneratorConstants.serializePackage(__pack: Package): ByteArrayOutputStream;
var
stream: ByteArrayOutputStream;
begin
stream := ByteArrayOutputStream.create();
try
with AVTOORecompilable, DataOutputStream.create(stream), bigEndianDataOutput do try
writeInt(CHUNK_PACK);
writeShort(__pack.attributes);
writeInt(indexAcquire(__pack.specialCanonicalName));
finally
free();
end;
except
stream.free();
raise;
end;
result := stream;
end;
function BinarySourceGeneratorConstants.serializeClassType(__type: ClassType): ByteArrayOutputStream;
var
index: int;
supertype: ClassType;
stream: ByteArrayOutputStream;
begin
stream := ByteArrayOutputStream.create();
try
with AVTOORecompilable, DataOutputStream.create(stream), bigEndianDataOutput do try
writeInt(CHUNK_TYPE);
writeShort(__type.attributes);
writeInt(indexAcquire(__type.parentPackage));
writeInt(indexAcquire(__type.specialSimpleName));
if __type.isHelper() then begin
writeInt(indexAcquire(__type.getHelperForType().specialCanonicalName));
end else begin
supertype := __type.getSuperclassType();
if supertype = nil then begin
writeInt(0);
end else begin
writeInt(indexAcquire(supertype.specialCanonicalName));
end;
for index := 0 to __type.getSuperservicesLength() - 1 do begin
writeInt(indexAcquire(__type.getSuperserviceTypeAt(index).specialCanonicalName));
end;
end;
finally
free();
end;
except
stream.free();
raise;
end;
result := stream;
end;
function BinarySourceGeneratorConstants.serializeClassField(__field: Field): ByteArrayOutputStream;
var
value: Constant;
stream: ByteArrayOutputStream;
begin
stream := ByteArrayOutputStream.create();
try
with AVTOORecompilable, DataOutputStream.create(stream), bigEndianDataOutput do try
writeInt(CHUNK_CFLD);
writeShort(__field.attributes);
writeInt(indexAcquire(__field.&type));
writeInt(indexAcquire(__field.specialSimpleName));
value := __field.value;
if value <> nil then writeInt(indexAcquire(value));
finally
free();
end;
except
stream.free();
raise;
end;
result := stream;
end;
function BinarySourceGeneratorConstants.serializeStructField(__field: Field): ByteArrayOutputStream;
var
stream: ByteArrayOutputStream;
begin
stream := ByteArrayOutputStream.create();
try
with AVTOORecompilable, DataOutputStream.create(stream), bigEndianDataOutput do try
writeInt(CHUNK_SFLD);
writeShort(__field.attributes);
writeInt(indexAcquire(__field.&type));
writeInt(indexAcquire(__field.specialSimpleName));
writeInt(__field.capacity);
writeInt(__field.structOffset);
finally
free();
end;
except
stream.free();
raise;
end;
result := stream;
end;
function BinarySourceGeneratorConstants.serializeProperty(__property: &Property): ByteArrayOutputStream;
var
stream: ByteArrayOutputStream;
begin
stream := ByteArrayOutputStream.create();
try
with AVTOORecompilable, DataOutputStream.create(stream), bigEndianDataOutput do try
writeInt(CHUNK_PROP);
writeShort(__property.attributes);
writeInt(indexAcquire(__property.&type));
writeInt(indexAcquire(__property.specialSimpleName));
writeInt(indexAcquire(__property.indexMember));
writeInt(indexAcquire(__property.storedMember));
writeInt(indexAcquire(__property.readMember));
writeInt(indexAcquire(__property.writeMember));
finally
free();
end;
except
stream.free();
raise;
end;
result := stream;
end;
function BinarySourceGeneratorConstants.serializeCallable(__callable: Callable): ByteArrayOutputStream;
var
index: int;
length: int;
stream: ByteArrayOutputStream;
begin
stream := ByteArrayOutputStream.create();
try
with AVTOORecompilable, DataOutputStream.create(stream), bigEndianDataOutput do try
writeInt(CHUNK_OPER);
writeShort(__callable.attributes);
writeInt(indexAcquire(__callable.&type));
writeInt(indexAcquire(__callable.specialSimpleName));
with __callable.arguments do begin
length := getLength();
writeShort(length);
for index := 0 to length - 1 do with readComponent(index) do begin
writeInt(indexAcquire(&type));
writeInt(indexAcquire(specialSimpleName));
end;
end;
finally
free();
end;
except
stream.free();
raise;
end;
result := stream;
end;
function BinarySourceGeneratorConstants.serializeMethod(__method: Method): ByteArrayOutputStream;
var
index: int;
length: int;
stream: ByteArrayOutputStream;
begin
stream := ByteArrayOutputStream.create();
try
with AVTOORecompilable, DataOutputStream.create(stream), bigEndianDataOutput do try
writeInt(CHUNK_METH);
writeShort(__method.attributes);
writeInt(indexAcquire(__method.&type));
writeInt(indexAcquire(__method.specialSimpleName));
with __method.arguments do begin
length := getLength();
writeShort(length);
for index := 0 to length - 1 do with readComponent(index) do begin
writeInt(indexAcquire(&type));
writeInt(indexAcquire(specialSimpleName));
end;
end;
for index := 0 to __method.getThrowablesLength() - 1 do begin
writeInt(indexAcquire(__method.getThrowableTypeAt(index).specialCanonicalName));
end;
finally
free();
end;
except
stream.free();
raise;
end;
result := stream;
end;
function BinarySourceGeneratorConstants.serializeCode(__code: Code): ByteArrayOutputStream;
label
break_label0;
type
HashtableOfAnsiStringToType = specialize HashtableOfAnsiString<&Type>;
var
cur: int;
max: int;
min: int;
store: int;
index: int;
ivalue: int;
jvalue: int;
cindex: int;
jindex: int;
length: int;
jlength: int;
encoded: int;
lastIndex: int;
lineIndex: int;
primLength: int;
refsLength: int;
formInstruction: int;
nodeInstruction: int;
name: AnsiString;
__end: Node;
block: Node;
target: Node;
__node: Node;
__begin: Node;
__type: &Type;
__local: Local;
oldType: &Type;
refObj: TObject;
refInt: IUnknown;
jumpDefault: Node;
__index: Constant;
__length: Constant;
operandC: Constant;
newType: TableItem;
__global: TableItem;
operandI: TableItem;
thisArgument: Local;
__constant: Constant;
__fieldoid: TableItem;
__callable: TableItem;
primTable: HashtableOfAnsiStringToType;
refsTable: HashtableOfAnsiStringToType;
stream: ByteArrayOutputStream;
begin
stream := ByteArrayOutputStream.create();
try
with AVTOORecompilable, DataOutputStream.create(stream), bigEndianDataOutput do try
writeInt(CHUNK_CODE);
begin
primTable := nil;
refsTable := nil;
try
primTable := HashtableOfAnsiStringToType.create();
refsTable := HashtableOfAnsiStringToType.create();
with __code.locals do for index := 0 to getLength() - 1 do with readComponent(index) do if not isConstant() then begin
__type := &type;
name := specialSimpleName;
if __type.isPrimitive() then begin
if not primTable.contains(name) or (primTable[name].fieldWidth < __type.fieldWidth) then begin
primTable[name] := __type;
end;
end else begin
if not refsTable.contains(name) then begin
refsTable[name] := __type;
end;
end;
end;
primLength := primTable.length;
refsLength := refsTable.length;
length := primLength + refsLength;
if length + CoInt.MIN_VALUE > $ffff + CoInt.MIN_VALUE then begin
raise UnencodableDataException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.generator.UNIT_NAME, 'not-encodable.too-many-locals'), [
CoObject.create(__code.parentCallable)
]
));
end;
writeShort(length);
for index := 0 to primLength - 1 do begin
name := primTable.keyAt(index);
__type := primTable[name];
writeInt(indexAcquire(__type));
writeInt(indexAcquire(name));
end;
for index := 0 to refsLength - 1 do begin
name := refsTable.keyAt(index);
__type := refsTable[name];
writeInt(indexAcquire(__type));
writeInt(indexAcquire(name));
end;
finally
primTable.free();
refsTable.free();
end;
end;
thisArgument := __code.parentCallable.arguments.thisArgument;
lastIndex := -1;
for cindex := 0 to __code.getLength() - 1 do begin
__node := __code.readComponent(cindex);
begin
lineIndex := __node.location[0];
if (lineIndex >= 0) and (lineIndex <> lastIndex) then begin
lastIndex := lineIndex;
encoded := encodeDeclare(false, lineIndex);
if isLongEncoded(encoded) then begin
writeInt(encoded);
end else begin
writeShort(encoded);
end;
end;
lineIndex := __node.debugIndex;
if lineIndex >= 0 then begin
encoded := encodeDeclare(true, not lineIndex);
if isLongEncoded(encoded) then begin
writeInt(encoded);
end else begin
writeShort(encoded);
end;
end;
lineIndex := __node.labelIndex;
if lineIndex >= 0 then begin
encoded := encodeDeclare(true, lineIndex);
if isLongEncoded(encoded) then begin
writeInt(encoded);
end else begin
writeShort(encoded);
end;
end;
end;
jlength := __node.getJumpCasesLength();
nodeInstruction := __node.instruction;
if jlength > 0 then begin
formInstruction := FLAG_BOOLEAN_JUMP;
end else begin
formInstruction := 0;
end;
case nodeInstruction of
METHOD_ENTER: begin
writeShort(INST_METHOD_ENTER);
writeIndex((__node.reference1 as CoInt).asInt());
continue;
end;
SWAP: begin
__type := __node.operand1 as &Type;
writeShort(INST_SWAP or encodeType(__type));
continue;
end;
FCT_BOUND,
FCT_BEGIN,
FCT_END: begin
writeShort(INST_BOUND);
continue;
end;
FCT_THROW: begin
__type := __node.reference1 as &Type;
writeShort(INST_THROW);
writeIndex(indexAcquire(__type));
continue;
end;
LOAD_STATIC: begin
__global := __node.operand1;
if __node.weak then begin
writeShort(INST_LOAD_STATICW);
writeIndex(indexAcquire(__global));
continue;
end;
writeShort(formInstruction or INST_LOAD_STATIC);
writeIndex(indexAcquire(__global));
end;
LOAD_LOCAL: begin
__local := __node.operand1 as Local;
if __node.weak then begin
writeShort(INST_LOAD_LOCALW or encodeType(TYP_REF));
if __local = thisArgument then begin
writeIndex(0);
continue;
end;
writeIndex(indexOf(__local.specialSimpleName));
continue;
end;
writeShort(formInstruction or INST_LOAD_LOCAL or encodeType(__local.&type));
if __local = thisArgument then begin
writeIndex(0);
goto break_label0;
end;
writeIndex(indexOf(__local.specialSimpleName));
end;
LOAD_CONST: begin
__constant := __node.operandC;
if __constant.isReference() then begin
refObj := __constant.asObject();
if refObj = nil then begin
writeShort(INST_LOAD_CONST_NULL);
continue;
end;
if refObj is RequiredReflectItem then begin
if __node.weak then begin
writeShort(INST_LOAD_CONSTW);
end else begin
writeShort(INST_LOAD_CONST);
end;
writeIndex(indexAcquire(RequiredReflectItem(refObj)));
continue;
end;
refInt := __constant.asInterface();
if refInt is Value then begin
writeShort(INST_LOAD_CONST);
writeIndex(indexAcquire((refInt as Value).asUnicodeString()));
continue;
end;
raise UnencodableDataException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.generator.UNIT_NAME, 'not-encodable.constant-value'), [
CoAnsiString.create(refObj.getClass().getCanonicalName())
]
));
end;
__type := __constant.&type;
if __type.isBoolean() then begin
if __constant.asBoolean() then begin
writeShort(INST_LOAD_CONST_BYTE or $ff);
continue;
end;
writeShort(INST_LOAD_CONST_BYTE or $00);
continue;
end;
if __type.isInt() then begin
ivalue := __constant.asInt();
if (ivalue >= CoByte.MIN_VALUE) and (ivalue <= CoByte.MAX_VALUE) then begin
writeShort(INST_LOAD_CONST_BYTE or __constant.asByte() and $ff);
continue;
end;
if (ivalue >= CoShort.MIN_VALUE) and (ivalue <= CoShort.MAX_VALUE) then begin
writeShort(INST_LOAD_CONST_SHORT);
writeShort(ivalue);
continue;
end;
writeShort(INST_LOAD_CONST_INT);
writeInt(ivalue);
continue;
end;
writeShort(INST_LOAD_CONST);
writeIndex(indexAcquire(__constant));
continue;
end;
READ_ELEMENT: begin
__type := __node.operand1 as &Type;
__index := __node.operandC;
if __index <> nil then begin
writeShort(INST_READ_ELEMENTI or encodeVectorIndex(__index.asInt()) or encodeType(__type));
continue;
end;
writeShort(INST_READ_ELEMENT or encodeType(__type));
continue;
end;
READ_COMPONENT: begin
__type := __node.operand1 as &Type;
operandI := __node.operand2;
operandC := __node.operandC;
writeShort(formInstruction or INST_READ_COMPONENT or encodeOperand(operandC, operandI) or encodeType(__type));
if (operandC <> nil) or (operandI <> nil) then writeIndex(getOperandIndex(operandC, operandI, thisArgument));
end;
READ_FIELD: begin
__fieldoid := __node.operand1;
operandI := __node.operand2;
operandC := __node.operandC;
writeShort(formInstruction or INST_READ_FIELD or encodeOperand(operandC, operandI));
writeIndex(indexAcquire(__fieldoid));
if (operandC <> nil) or (operandI <> nil) then writeIndex(getOperandIndex(operandC, operandI, thisArgument));
end;
READ_SPECIAL: begin
__fieldoid := __node.operand1;
operandI := __node.operand2;
operandC := __node.operandC;
writeShort(formInstruction or INST_READ_SPECIAL or encodeOperand(operandC, operandI));
writeIndex(indexAcquire(__fieldoid));
if (operandC <> nil) or (operandI <> nil) then writeIndex(getOperandIndex(operandC, operandI, thisArgument));
end;
READ_PROPERTY: begin
__fieldoid := __node.operand1;
operandI := __node.operand2;
operandC := __node.operandC;
writeShort(formInstruction or INST_READ_PROPERTY or encodeOperand(operandC, operandI));
writeIndex(indexAcquire(__fieldoid));
if (operandC <> nil) or (operandI <> nil) then writeIndex(getOperandIndex(operandC, operandI, thisArgument));
end;
STORE_STATIC: begin
__global := __node.operand1;
__constant := __node.operandC;
if __constant <> nil then begin
if __constant.isNull() then begin
writeShort(INST_STORE_STATIC_NULL);
writeIndex(indexAcquire(__global));
continue;
end;
__type := __constant.&type;
if __type.isBoolean() then begin
writeShort(formInstruction or INST_STORE_STATIC_SHORT);
writeIndex(indexAcquire(__global));
if __constant.asBoolean() then begin
writeShort(-1);
goto break_label0;
end;
writeShort(0);
goto break_label0;
end;
if __type.isInt() then begin
ivalue := __constant.asInt();
if (ivalue >= CoShort.MIN_VALUE) and (ivalue <= CoShort.MAX_VALUE) then begin
writeShort(INST_STORE_STATIC_SHORT);
writeIndex(indexAcquire(__global));
writeShort(ivalue);
continue;
end;
writeShort(INST_STORE_STATIC_INT);
writeIndex(indexAcquire(__global));
writeInt(ivalue);
continue;
end;
raise UnencodableDataException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.generator.UNIT_NAME, 'not-encodable.assignable.global'), [
CoObject.create(__type)
]
));
end;
writeShort(formInstruction or INST_STORE_STATIC);
writeIndex(indexAcquire(__global));
end;
STORE_LOCAL,
DECLARE_WITH,
DECLARE_LOCAL: begin
store := nodeInstruction - (STORE_LOCAL - STORE_NORMAL);
__local := __node.operand1 as Local;
__constant := __node.operandC;
if __constant <> nil then begin
if __constant.isNull() then begin
writeShort(INST_STORE_LOCAL_NULL or encodeStore(store) or encodeType(TYP_REF));
writeIndex(getOperandIndex(nil, __local, thisArgument));
continue;
end;
__type := __constant.&type;
if __type.isBoolean() then begin
writeShort(formInstruction or INST_STORE_LOCAL_SHORT or encodeStore(store) or encodeType(TYP_BOOLEAN));
writeIndex(getOperandIndex(nil, __local, thisArgument));
if __constant.asBoolean() then begin
writeShort(-1);
goto break_label0;
end;
writeShort(0);
goto break_label0;
end;
if __type.isInt() then begin
ivalue := __constant.asInt();
if (ivalue >= CoShort.MIN_VALUE) and (ivalue <= CoShort.MAX_VALUE) then begin
writeShort(INST_STORE_LOCAL_SHORT or encodeStore(store) or encodeType(__type));
writeIndex(getOperandIndex(nil, __local, thisArgument));
writeShort(ivalue);
continue;
end;
writeShort(INST_STORE_LOCAL_INT or encodeStore(store) or encodeType(__type));
writeIndex(getOperandIndex(nil, __local, thisArgument));
writeInt(ivalue);
continue;
end;
raise UnencodableDataException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.generator.UNIT_NAME, 'not-encodable.assignable.local'), [
CoObject.create(__type)
]
));
end;
writeShort(formInstruction or INST_STORE_LOCAL or encodeStore(store) or encodeType(__local.&type));
writeIndex(getOperandIndex(nil, __local, thisArgument));
end;
INC_PRED_LOAD_LOCAL: begin
__local := __node.operand1 as Local;
writeShort(INST_INC_PRED_LOAD_LOCAL or encodeType(__local.&type));
writeIndex(indexOf(__local.specialSimpleName));
continue;
end;
DEC_PRED_LOAD_LOCAL: begin
__local := __node.operand1 as Local;
writeShort(INST_DEC_PRED_LOAD_LOCAL or encodeType(__local.&type));
writeIndex(indexOf(__local.specialSimpleName));
continue;
end;
INC_POST_LOAD_LOCAL: begin
__local := __node.operand1 as Local;
writeShort(INST_INC_POST_LOAD_LOCAL or encodeType(__local.&type));
writeIndex(indexOf(__local.specialSimpleName));
continue;
end;
DEC_POST_LOAD_LOCAL: begin
__local := __node.operand1 as Local;
writeShort(INST_DEC_POST_LOAD_LOCAL or encodeType(__local.&type));
writeIndex(indexOf(__local.specialSimpleName));
continue;
end;
WRITE_COMPONENT: begin
__type := __node.operand1 as &Type;
writeShort(formInstruction or INST_WRITE_COMPONENT or encodeType(__type));
end;
WRITE_FIELD: begin
__fieldoid := __node.operand1;
writeShort(formInstruction or INST_WRITE_FIELD);
writeIndex(indexAcquire(__fieldoid));
end;
WRITE_SPECIAL: begin
__fieldoid := __node.operand1;
writeShort(formInstruction or INST_WRITE_SPECIAL);
writeIndex(indexAcquire(__fieldoid));
end;
WRITE_PROPERTY: begin
__fieldoid := __node.operand1;
writeShort(formInstruction or INST_WRITE_PROPERTY);
writeIndex(indexAcquire(__fieldoid));
end;
FCT_JUMP,
FCT_RETURN,
FCT_BRANCH: begin
if (nodeInstruction = FCT_BRANCH) and (jlength > 0) then begin
min := __node.getJumpCaseValueAt(0);
max := min;
for jindex := 1 to jlength - 1 do begin
cur := __node.getJumpCaseValueAt(jindex);
if min > cur then min := cur;
if max < cur then max := cur;
end;
jumpDefault := __node.jumpDefault;
if (long(max) - min + 2) <= (long(jlength) shl 1) then begin
writeShort(INST_SWITCH_TABLE);
writeInt(min);
jlength := max - min + 1;
writeIndex(jlength);
jvalue := min;
for jindex := 0 to jlength - 1 do begin
target := __node.getJumpCase(jvalue);
if target = nil then target := jumpDefault;
writeLabel(target);
inc(jvalue);
end;
end else begin
writeShort(INST_SWITCH_LOOKUP);
writeIndex(jlength);
for jindex := 0 to jlength - 1 do begin
jvalue := __node.getJumpCaseValueAt(jindex);
target := __node.getJumpCaseNodeAt(jindex);
writeInt(jvalue);
writeLabel(target);
end;
end;
writeLabel(jumpDefault);
continue;
end;
writeShort(INST_JUMP);
writeLabel(__node.jumpDefault);
continue;
end;
LOAD_INTERRUPT: begin
__callable := __node.operand1;
writeShort(INST_LOAD_INTERRUPT);
writeIndex(indexAcquire(__callable));
continue;
end;
REF_EQ: begin
operandI := __node.operand1;
operandC := __node.operandC;
if __node.weak then begin
formInstruction := formInstruction or INST_REF_EQW;
end else begin
formInstruction := formInstruction or INST_REF_EQ;
end;
writeShort(formInstruction or encodeOperand(operandC, operandI) or encodeType(TYP_REF));
if (operandC <> nil) or (operandI <> nil) then writeIndex(getOperandIndex(operandC, operandI, thisArgument));
end;
REF_NE: begin
operandI := __node.operand1;
operandC := __node.operandC;
if __node.weak then begin
formInstruction := formInstruction or INST_REF_NEW;
end else begin
formInstruction := formInstruction or INST_REF_NE;
end;
writeShort(formInstruction or encodeOperand(operandC, operandI) or encodeType(TYP_REF));
if (operandC <> nil) or (operandI <> nil) then writeIndex(getOperandIndex(operandC, operandI, thisArgument));
end;
REF_IS_NULL: begin
if __node.weak then begin
formInstruction := formInstruction or INST_REF_IS_NULLW;
end else begin
formInstruction := formInstruction or INST_REF_IS_NULL;
end;
writeShort(formInstruction or encodeType(TYP_REF));
end;
REF_IS_OBJECT: begin
if __node.weak then begin
formInstruction := formInstruction or INST_REF_IS_OBJECTW;
end else begin
formInstruction := formInstruction or INST_REF_IS_OBJECT;
end;
writeShort(formInstruction or encodeType(TYP_REF));
end;
CLINIT_TRY_LOCK: begin
operandI := __node.operand1;
writeShort(formInstruction or INST_CLINIT_TRY_LOCK);
writeIndex(indexAcquire(operandI));
end;
CLINIT_UNLOCK: begin
operandI := __node.operand1;
writeShort(INST_CLINIT_UNLOCK);
writeIndex(indexAcquire(operandI));
continue;
end;
MONITOR_ENTER: begin
writeShort(INST_MONITOR_ENTER or encodeType(TYP_REF));
continue;
end;
MONITOR_LEAVE: begin
writeShort(INST_MONITOR_LEAVE or encodeType(TYP_REF));
continue;
end;
FINALLY_ENTER: begin
writeShort(INST_FINALLY_ENTER);
continue;
end;
FINALLY_LEAVE: begin
writeShort(INST_FINALLY_LEAVE);
continue;
end;
NEW_ARRAY: begin
operandI := __node.operand1;
__length := __node.operandC;
writeShort(INST_NEW_ARRAY);
writeIndex(indexAcquire(operandI));
writeInt(__length.asInt());
continue;
end;
INVOKE_FINALLY: begin
target := __node.reference1 as Node;
writeShort(INST_INVOKE_FINALLY);
writeLabel(target);
continue;
end;
INVOKE_STATIC: begin
__callable := __node.operand1;
if __node.weak then begin
formInstruction := formInstruction or INST_INVOKE_STATICD;
end else begin
formInstruction := formInstruction or INST_INVOKE_STATIC;
end;
writeShort(formInstruction);
writeIndex(indexAcquire(__callable));
end;
INVOKE_SPECIAL: begin
__callable := __node.operand1;
if __node.weak then begin
formInstruction := formInstruction or INST_INVOKE_SPECIALD;
end else begin
formInstruction := formInstruction or INST_INVOKE_SPECIAL;
end;
writeShort(formInstruction);
writeIndex(indexAcquire(__callable));
end;
INVOKE_VIRTUAL: begin
__callable := __node.operand1;
if __node.weak then begin
formInstruction := formInstruction or INST_INVOKE_VIRTUALD;
end else begin
formInstruction := formInstruction or INST_INVOKE_VIRTUAL;
end;
writeShort(formInstruction);
writeIndex(indexAcquire(__callable));
end;
INVOKE_SERVICE: begin
__callable := __node.operand1;
if __node.weak then begin
formInstruction := formInstruction or INST_INVOKE_SERVICED;
end else begin
formInstruction := formInstruction or INST_INVOKE_SERVICE;
end;
writeShort(formInstruction);
writeIndex(indexAcquire(__callable));
end;
O_VECT_DIV: begin
__type := __node.operand1 as &Type;
operandI := __node.operand2;
operandC := __node.operandC;
writeShort(INST_VECT_DIV or encodeOperand(operandC, operandI) or encodeType(__type));
if (operandC <> nil) or (operandI <> nil) then writeIndex(getOperandIndex(operandC, operandI, thisArgument));
continue;
end;
O_VECT_PCK: begin
__type := __node.operand1 as &Type;
writeShort(INST_VECT_PCK or encodeType(__type));
continue;
end;
O_VECT_LUP: begin
__type := __node.operand1 as &Type;
writeShort(INST_VECT_LUP or encodeType(__type));
continue;
end;
O_VECT_UUP: begin
__type := __node.operand1 as &Type;
writeShort(INST_VECT_UUP or encodeType(__type));
continue;
end;
O_VECT_MUL: begin
__type := __node.operand1 as &Type;
operandI := __node.operand2;
operandC := __node.operandC;
writeShort(INST_VECT_MUL or encodeOperand(operandC, operandI) or encodeType(__type));
if (operandC <> nil) or (operandI <> nil) then writeIndex(getOperandIndex(operandC, operandI, thisArgument));
continue;
end;
O_VECT_SHL: begin
__type := __node.operand1 as &Type;
operandI := __node.operand2;
operandC := __node.operandC;
writeShort(INST_VECT_SHL or encodeOperand(operandC, operandI) or encodeType(__type));
if (operandC <> nil) or (operandI <> nil) then writeIndex(getOperandIndex(operandC, operandI, thisArgument));
continue;
end;
O_VECT_SHR: begin
__type := __node.operand1 as &Type;
operandI := __node.operand2;
operandC := __node.operandC;
writeShort(INST_VECT_SHR or encodeOperand(operandC, operandI) or encodeType(__type));
if (operandC <> nil) or (operandI <> nil) then writeIndex(getOperandIndex(operandC, operandI, thisArgument));
continue;
end;
O_VECT_SHRU: begin
__type := __node.operand1 as &Type;
operandI := __node.operand2;
operandC := __node.operandC;
writeShort(INST_VECT_SHRU or encodeOperand(operandC, operandI) or encodeType(__type));
if (operandC <> nil) or (operandI <> nil) then writeIndex(getOperandIndex(operandC, operandI, thisArgument));
continue;
end;
O_VECT_ADD: begin
__type := __node.operand1 as &Type;
operandI := __node.operand2;
operandC := __node.operandC;
writeShort(INST_VECT_ADD or encodeOperand(operandC, operandI) or encodeType(__type));
if (operandC <> nil) or (operandI <> nil) then writeIndex(getOperandIndex(operandC, operandI, thisArgument));
continue;
end;
O_VECT_SUB: begin
__type := __node.operand1 as &Type;
operandI := __node.operand2;
operandC := __node.operandC;
writeShort(INST_VECT_SUB or encodeOperand(operandC, operandI) or encodeType(__type));
if (operandC <> nil) or (operandI <> nil) then writeIndex(getOperandIndex(operandC, operandI, thisArgument));
continue;
end;
O_VECT_EQ: begin
__type := __node.operand1 as &Type;
operandI := __node.operand2;
operandC := __node.operandC;
writeShort(INST_VECT_EQ or encodeOperand(operandC, operandI) or encodeType(__type));
if (operandC <> nil) or (operandI <> nil) then writeIndex(getOperandIndex(operandC, operandI, thisArgument));
continue;
end;
O_VECT_NE: begin
__type := __node.operand1 as &Type;
operandI := __node.operand2;
operandC := __node.operandC;
writeShort(INST_VECT_NE or encodeOperand(operandC, operandI) or encodeType(__type));
if (operandC <> nil) or (operandI <> nil) then writeIndex(getOperandIndex(operandC, operandI, thisArgument));
continue;
end;
O_VECT_GT: begin
__type := __node.operand1 as &Type;
operandI := __node.operand2;
operandC := __node.operandC;
writeShort(INST_VECT_GT or encodeOperand(operandC, operandI) or encodeType(__type));
if (operandC <> nil) or (operandI <> nil) then writeIndex(getOperandIndex(operandC, operandI, thisArgument));
continue;
end;
O_VECT_GE: begin
__type := __node.operand1 as &Type;
operandI := __node.operand2;
operandC := __node.operandC;
writeShort(INST_VECT_GE or encodeOperand(operandC, operandI) or encodeType(__type));
if (operandC <> nil) or (operandI <> nil) then writeIndex(getOperandIndex(operandC, operandI, thisArgument));
continue;
end;
O_VECT_LT: begin
__type := __node.operand1 as &Type;
operandI := __node.operand2;
operandC := __node.operandC;
writeShort(INST_VECT_LT or encodeOperand(operandC, operandI) or encodeType(__type));
if (operandC <> nil) or (operandI <> nil) then writeIndex(getOperandIndex(operandC, operandI, thisArgument));
continue;
end;
O_VECT_LE: begin
__type := __node.operand1 as &Type;
operandI := __node.operand2;
operandC := __node.operandC;
writeShort(INST_VECT_LE or encodeOperand(operandC, operandI) or encodeType(__type));
if (operandC <> nil) or (operandI <> nil) then writeIndex(getOperandIndex(operandC, operandI, thisArgument));
continue;
end;
O_SCAL_DIV: begin
__type := __node.operand1 as &Type;
operandI := __node.operand2;
operandC := __node.operandC;
writeShort(INST_SCAL_DIV or encodeOperand(operandC, operandI) or encodeType(__type));
if (operandC <> nil) or (operandI <> nil) then writeIndex(getOperandIndex(operandC, operandI, thisArgument));
continue;
end;
O_SCAL_DIVU: begin
__type := __node.operand1 as &Type;
operandI := __node.operand2;
operandC := __node.operandC;
writeShort(INST_SCAL_DIVU or encodeOperand(operandC, operandI) or encodeType(__type));
if (operandC <> nil) or (operandI <> nil) then writeIndex(getOperandIndex(operandC, operandI, thisArgument));
continue;
end;
O_SCAL_REM: begin
__type := __node.operand1 as &Type;
operandI := __node.operand2;
operandC := __node.operandC;
writeShort(INST_SCAL_REM or encodeOperand(operandC, operandI) or encodeType(__type));
if (operandC <> nil) or (operandI <> nil) then writeIndex(getOperandIndex(operandC, operandI, thisArgument));
continue;
end;
O_SCAL_REMU: begin
__type := __node.operand1 as &Type;
operandI := __node.operand2;
operandC := __node.operandC;
writeShort(INST_SCAL_REMU or encodeOperand(operandC, operandI) or encodeType(__type));
if (operandC <> nil) or (operandI <> nil) then writeIndex(getOperandIndex(operandC, operandI, thisArgument));
continue;
end;
O_SCAL_MUL: begin
__type := __node.operand1 as &Type;
operandI := __node.operand2;
operandC := __node.operandC;
writeShort(INST_SCAL_MUL or encodeOperand(operandC, operandI) or encodeType(__type));
if (operandC <> nil) or (operandI <> nil) then writeIndex(getOperandIndex(operandC, operandI, thisArgument));
continue;
end;
O_SCAL_SHL: begin
__type := __node.operand1 as &Type;
operandI := __node.operand2;
operandC := __node.operandC;
writeShort(INST_SCAL_SHL or encodeOperand(operandC, operandI) or encodeType(__type));
if (operandC <> nil) or (operandI <> nil) then writeIndex(getOperandIndex(operandC, operandI, thisArgument));
continue;
end;
O_SCAL_SHR: begin
__type := __node.operand1 as &Type;
operandI := __node.operand2;
operandC := __node.operandC;
writeShort(INST_SCAL_SHR or encodeOperand(operandC, operandI) or encodeType(__type));
if (operandC <> nil) or (operandI <> nil) then writeIndex(getOperandIndex(operandC, operandI, thisArgument));
continue;
end;
O_SCAL_SHRU: begin
__type := __node.operand1 as &Type;
operandI := __node.operand2;
operandC := __node.operandC;
writeShort(INST_SCAL_SHRU or encodeOperand(operandC, operandI) or encodeType(__type));
if (operandC <> nil) or (operandI <> nil) then writeIndex(getOperandIndex(operandC, operandI, thisArgument));
continue;
end;
O_SCAL_ADD: begin
__type := __node.operand1 as &Type;
operandI := __node.operand2;
operandC := __node.operandC;
writeShort(INST_SCAL_ADD or encodeOperand(operandC, operandI) or encodeType(__type));
if (operandC <> nil) or (operandI <> nil) then writeIndex(getOperandIndex(operandC, operandI, thisArgument));
continue;
end;
O_SCAL_SUB: begin
__type := __node.operand1 as &Type;
operandI := __node.operand2;
operandC := __node.operandC;
writeShort(INST_SCAL_SUB or encodeOperand(operandC, operandI) or encodeType(__type));
if (operandC <> nil) or (operandI <> nil) then writeIndex(getOperandIndex(operandC, operandI, thisArgument));
continue;
end;
O_SCAL_EQ: begin
__type := __node.operand1 as &Type;
operandI := __node.operand2;
operandC := __node.operandC;
writeShort(formInstruction or INST_SCAL_EQ or encodeOperand(operandC, operandI) or encodeType(__type));
if (operandC <> nil) or (operandI <> nil) then writeIndex(getOperandIndex(operandC, operandI, thisArgument));
end;
O_SCAL_NE: begin
__type := __node.operand1 as &Type;
operandI := __node.operand2;
operandC := __node.operandC;
writeShort(formInstruction or INST_SCAL_NE or encodeOperand(operandC, operandI) or encodeType(__type));
if (operandC <> nil) or (operandI <> nil) then writeIndex(getOperandIndex(operandC, operandI, thisArgument));
end;
O_SCAL_GT: begin
__type := __node.operand1 as &Type;
operandI := __node.operand2;
operandC := __node.operandC;
writeShort(formInstruction or INST_SCAL_GT or encodeOperand(operandC, operandI) or encodeType(__type));
if (operandC <> nil) or (operandI <> nil) then writeIndex(getOperandIndex(operandC, operandI, thisArgument));
end;
O_SCAL_GE: begin
__type := __node.operand1 as &Type;
operandI := __node.operand2;
operandC := __node.operandC;
writeShort(formInstruction or INST_SCAL_GE or encodeOperand(operandC, operandI) or encodeType(__type));
if (operandC <> nil) or (operandI <> nil) then writeIndex(getOperandIndex(operandC, operandI, thisArgument));
end;
O_SCAL_LT: begin
__type := __node.operand1 as &Type;
operandI := __node.operand2;
operandC := __node.operandC;
writeShort(formInstruction or INST_SCAL_LT or encodeOperand(operandC, operandI) or encodeType(__type));
if (operandC <> nil) or (operandI <> nil) then writeIndex(getOperandIndex(operandC, operandI, thisArgument));
end;
O_SCAL_LE: begin
__type := __node.operand1 as &Type;
operandI := __node.operand2;
operandC := __node.operandC;
writeShort(formInstruction or INST_SCAL_LE or encodeOperand(operandC, operandI) or encodeType(__type));
if (operandC <> nil) or (operandI <> nil) then writeIndex(getOperandIndex(operandC, operandI, thisArgument));
end;
O_VECT_NEG: begin
__type := __node.operand1 as &Type;
writeShort(INST_VECT_NEG or encodeType(__type));
continue;
end;
CAST_TO: begin
newType := __node.operand1;
oldType := __node.operand2 as &Type;
writeShort(INST_CAST_TO or encodeType(oldType));
writeIndex(indexAcquire(newType));
continue;
end;
INC_LOCAL: begin
__local := __node.operand1 as Local;
writeShort(INST_INC_LOCAL or encodeType(__local.&type));
writeIndex(indexOf(__local.specialSimpleName));
continue;
end;
DEC_LOCAL: begin
__local := __node.operand1 as Local;
writeShort(INST_DEC_LOCAL or encodeType(__local.&type));
writeIndex(indexOf(__local.specialSimpleName));
continue;
end;
O_BIT_NOT: begin
__type := __node.operand1 as &Type;
writeShort(formInstruction or INST_BIT_NOT or encodeType(__type));
end;
O_BIT_AND: begin
__type := __node.operand1 as &Type;
operandI := __node.operand2;
operandC := __node.operandC;
writeShort(formInstruction or INST_BIT_AND or encodeOperand(operandC, operandI) or encodeType(__type));
if (operandC <> nil) or (operandI <> nil) then writeIndex(getOperandIndex(operandC, operandI, thisArgument));
end;
O_BIT_OR: begin
__type := __node.operand1 as &Type;
operandI := __node.operand2;
operandC := __node.operandC;
writeShort(formInstruction or INST_BIT_OR or encodeOperand(operandC, operandI) or encodeType(__type));
if (operandC <> nil) or (operandI <> nil) then writeIndex(getOperandIndex(operandC, operandI, thisArgument));
end;
O_BIT_XOR: begin
__type := __node.operand1 as &Type;
operandI := __node.operand2;
operandC := __node.operandC;
writeShort(formInstruction or INST_BIT_XOR or encodeOperand(operandC, operandI) or encodeType(__type));
if (operandC <> nil) or (operandI <> nil) then writeIndex(getOperandIndex(operandC, operandI, thisArgument));
end;
DUP1: begin
__type := __node.operand1 as &Type;
writeShort(INST_DUP1 or encodeType(__type));
continue;
end;
DUP2: begin
__type := __node.operand1 as &Type;
writeShort(INST_DUP2 or encodeType(__type));
continue;
end;
O_VECT_HMUL: begin
__type := __node.operand1 as &Type;
operandI := __node.operand2;
operandC := __node.operandC;
writeShort(INST_VECT_HMUL or encodeOperand(operandC, operandI) or encodeType(__type));
if (operandC <> nil) or (operandI <> nil) then writeIndex(getOperandIndex(operandC, operandI, thisArgument));
continue;
end;
O_VECT_HMULU: begin
__type := __node.operand1 as &Type;
operandI := __node.operand2;
operandC := __node.operandC;
writeShort(INST_VECT_HMULU or encodeOperand(operandC, operandI) or encodeType(__type));
if (operandC <> nil) or (operandI <> nil) then writeIndex(getOperandIndex(operandC, operandI, thisArgument));
continue;
end;
O_VECT_SADD: begin
__type := __node.operand1 as &Type;
operandI := __node.operand2;
operandC := __node.operandC;
writeShort(INST_VECT_SADD or encodeOperand(operandC, operandI) or encodeType(__type));
if (operandC <> nil) or (operandI <> nil) then writeIndex(getOperandIndex(operandC, operandI, thisArgument));
continue;
end;
O_VECT_SADDU: begin
__type := __node.operand1 as &Type;
operandI := __node.operand2;
operandC := __node.operandC;
writeShort(INST_VECT_SADDU or encodeOperand(operandC, operandI) or encodeType(__type));
if (operandC <> nil) or (operandI <> nil) then writeIndex(getOperandIndex(operandC, operandI, thisArgument));
continue;
end;
O_VECT_SSUB: begin
__type := __node.operand1 as &Type;
operandI := __node.operand2;
operandC := __node.operandC;
writeShort(INST_VECT_SSUB or encodeOperand(operandC, operandI) or encodeType(__type));
if (operandC <> nil) or (operandI <> nil) then writeIndex(getOperandIndex(operandC, operandI, thisArgument));
continue;
end;
O_VECT_SSUBU: begin
__type := __node.operand1 as &Type;
operandI := __node.operand2;
operandC := __node.operandC;
writeShort(INST_VECT_SSUBU or encodeOperand(operandC, operandI) or encodeType(__type));
if (operandC <> nil) or (operandI <> nil) then writeIndex(getOperandIndex(operandC, operandI, thisArgument));
continue;
end;
O_SCAL_NEG: begin
__type := __node.operand1 as &Type;
writeShort(INST_SCAL_NEG or encodeType(__type));
continue;
end;
EXP_INSTANCEOF: begin
__type := __node.operand1 as &Type;
writeShort(formInstruction or INST_INSTANCE_OF or encodeType(__type));
writeIndex(indexAcquire(__type));
end;
TEST_EQZ: begin
__type := __node.operand1 as &Type;
operandI := __node.operand2;
operandC := __node.operandC;
writeShort(formInstruction or INST_TEST_EQZ or encodeOperand(operandC, operandI) or encodeType(__type));
if (operandC <> nil) or (operandI <> nil) then writeIndex(getOperandIndex(operandC, operandI, thisArgument));
end;
TEST_NEZ: begin
__type := __node.operand1 as &Type;
operandI := __node.operand2;
operandC := __node.operandC;
writeShort(formInstruction or INST_TEST_NEZ or encodeOperand(operandC, operandI) or encodeType(__type));
if (operandC <> nil) or (operandI <> nil) then writeIndex(getOperandIndex(operandC, operandI, thisArgument));
end;
NEW_VECTOR: begin
__type := __node.operand1 as &Type;
writeShort(INST_NEW_VECTOR or encodeType(__type));
continue;
end;
NEW_INSTANCE: begin
operandI := __node.operand1;
writeShort(INST_NEW_INSTANCE);
writeIndex(indexAcquire(operandI));
continue;
end;
NEW_ARRAY_MONO: begin
operandI := __node.operand1;
writeShort(INST_NEW_ARRAY_MONO);
writeIndex(indexAcquire(operandI));
continue;
end;
NEW_ARRAY_MULTI: begin
operandI := __node.operand1;
writeShort(INST_NEW_ARRAY_MULTI);
writeIndex(indexAcquire(operandI));
continue;
end;
DUP1X1: begin
__type := __node.operand1 as &Type;
writeShort(INST_DUP1X1 or encodeType(__type));
continue;
end;
DUP1X2: begin
__type := __node.operand1 as &Type;
writeShort(INST_DUP1X2 or encodeType(__type));
continue;
end;
METHOD_LEAVE: begin
writeShort(INST_METHOD_LEAVE);
continue;
end;
EXCEPT_ENTER: begin
writeShort(INST_EXCEPT_ENTER);
continue;
end;
EXCEPT_TRY: begin
__begin := __node.reference1 as Node;
__end := __node.reference2 as Node;
writeShort(INST_EXCEPT_TRY);
writeLabel(__begin);
writeLabel(__end);
continue;
end;
EXCEPT_CATCH: begin
block := __node.reference1 as Node;
__type := __node.reference2 as &Type;
writeShort(INST_EXCEPT_CATCH);
writeLabel(block);
writeIndex(indexAcquire(__type));
continue;
end;
EXCEPT_FINALLY: begin
block := __node.reference1 as Node;
writeShort(INST_EXCEPT_FINALLY);
writeLabel(block);
continue;
end;
EXCEPT_LEAVE: begin
writeShort(INST_EXCEPT_LEAVE);
continue;
end;
else
raise UnencodableDataException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.generator.UNIT_NAME, 'not-encodable.instruction'), [
CoAnsiString.create(CoInt.toHexString(nodeInstruction))
]
));
end;
break_label0:
if (formInstruction and FLAG_BOOLEAN_JUMP) <> 0 then begin
writeLabel(__node.jumpIsTrue);
writeLabel(__node.jumpIsFalse);
end;
end;
finally
free();
end;
except
stream.free();
raise;
end;
result := stream;
end;
{%endregion}
{%region BinarySourceGeneratorCodeDataOutput }
procedure BinarySourceGeneratorCodeDataOutput.writeByte2(const value: byte2);
var
index: int;
begin
for index := 1 downto 0 do writeByte(value[index]);
end;
procedure BinarySourceGeneratorCodeDataOutput.writeByte4(const value: byte4);
var
index: int;
begin
for index := 3 downto 0 do writeByte(value[index]);
end;
procedure BinarySourceGeneratorCodeDataOutput.writeByte8(const value: byte8);
var
index: int;
begin
for index := 7 downto 0 do writeByte(value[index]);
end;
procedure BinarySourceGeneratorCodeDataOutput.writeShort2(const value: short2);
var
index: int;
begin
for index := 1 downto 0 do writeShort(value[index]);
end;
procedure BinarySourceGeneratorCodeDataOutput.writeShort4(const value: short4);
var
index: int;
begin
for index := 3 downto 0 do writeShort(value[index]);
end;
procedure BinarySourceGeneratorCodeDataOutput.writeShort8(const value: short8);
var
index: int;
begin
for index := 7 downto 0 do writeShort(value[index]);
end;
procedure BinarySourceGeneratorCodeDataOutput.writeInt2(const value: int2);
var
index: int;
begin
for index := 1 downto 0 do writeInt(value[index]);
end;
procedure BinarySourceGeneratorCodeDataOutput.writeInt4(const value: int4);
var
index: int;
begin
for index := 3 downto 0 do writeInt(value[index]);
end;
procedure BinarySourceGeneratorCodeDataOutput.writeInt8(const value: int8);
var
index: int;
begin
for index := 7 downto 0 do writeInt(value[index]);
end;
procedure BinarySourceGeneratorCodeDataOutput.writeLong2(const value: long2);
var
index: int;
begin
for index := 1 downto 0 do writeLong(value[index]);
end;
procedure BinarySourceGeneratorCodeDataOutput.writeLong4(const value: long4);
var
index: int;
begin
for index := 3 downto 0 do writeLong(value[index]);
end;
procedure BinarySourceGeneratorCodeDataOutput.writeLong8(const value: long8);
var
index: int;
begin
for index := 7 downto 0 do writeLong(value[index]);
end;
procedure BinarySourceGeneratorCodeDataOutput.writeFloat2(const value: float2);
var
index: int;
begin
for index := 1 downto 0 do writeFloat(value[index]);
end;
procedure BinarySourceGeneratorCodeDataOutput.writeFloat4(const value: float4);
var
index: int;
begin
for index := 3 downto 0 do writeFloat(value[index]);
end;
procedure BinarySourceGeneratorCodeDataOutput.writeFloat8(const value: float8);
var
index: int;
begin
for index := 7 downto 0 do writeFloat(value[index]);
end;
procedure BinarySourceGeneratorCodeDataOutput.writeDouble2(const value: double2);
var
index: int;
begin
for index := 1 downto 0 do writeDouble(value[index]);
end;
procedure BinarySourceGeneratorCodeDataOutput.writeDouble4(const value: Double4);
var
index: int;
begin
for index := 3 downto 0 do writeDouble(value[index]);
end;
procedure BinarySourceGeneratorCodeDataOutput.writeDouble8(const value: double8);
var
index: int;
begin
for index := 7 downto 0 do writeDouble(value[index]);
end;
procedure BinarySourceGeneratorCodeDataOutput.writeIndex(index: int);
begin
if index <= CoShort.MAX_VALUE then begin
writeShort(index);
end else begin
writeInt(CoInt.MIN_VALUE or index);
end;
end;
procedure BinarySourceGeneratorCodeDataOutput.writeLabel(target: Node);
var
index: int;
encoded: int;
begin
index := target.debugIndex;
if index >= 0 then begin
encoded := AVTOORecompilable.encodeUsing(not index);
end else begin
index := target.labelIndex;
if index >= 0 then begin
encoded := AVTOORecompilable.encodeUsing(index);
end else begin
encoded := AVTOORecompilable.encodeNext();
end;
end;
if AVTOORecompilable.isLongEncoded(encoded) then begin
writeInt(encoded);
end else begin
writeShort(encoded);
end;
end;
{%endregion}
{%region AssemblerSourceGeneratorClassType }
function AssemblerSourceGeneratorClassType.hasOverriddingMembersFor(superservice: ClassType; isSuperclassesLook: boolean): boolean;
var
place: int;
index: int;
member: ProgrammeItem;
overridden: OverriddableMember;
overridding: OverriddableMember;
begin
if isSuperclassesLook then begin
place := Method.CURRENT_TYPE or Method.SUPERCLASSES;
end else begin
place := Method.CURRENT_TYPE;
end;
for index := superservice.getLength() - 1 downto 0 do begin
member := superservice.readComponent(index);
if not(member is OverriddableMember) then continue;
{ переопределённый член } overridden := OverriddableMember(member);
if (overridden.visibility < VIS_PROTECTED) or overridden.isAbstract() then continue;
{ переопределяющий член } overridding := overridden.overridesIn(self, place);
if (overridding <> nil) and (overridding.visibility >= VIS_PROTECTED) then begin
result := true;
exit;
end;
end;
result := false;
end;
{%endregion}
{%region} initialization
AssemblerSourcePrintStream.initialize();
{%endregion}
{%region} finalization
AssemblerSourcePrintStream.finalize();
{%endregion}
end.