/*
Генератор кода для языка программирования
Объектно-ориентированный продвинутый векторный транслятор
Copyright © 2021, 2024 Малик Разработчик
Это свободная программа: вы можете перераспространять ее и/или изменять
ее на условиях Стандартной общественной лицензии GNU в том виде,
в каком она была опубликована Фондом свободного программного обеспечения;
либо версии 3 лицензии, либо (по вашему выбору) любой более поздней версии.
Эта программа распространяется в надежде, что она будет полезной,
но БЕЗО ВСЯКИХ ГАРАНТИЙ; даже без неявной гарантии ТОВАРНОГО ВИДА
или ПРИГОДНОСТИ ДЛЯ ОПРЕДЕЛЕННЫХ ЦЕЛЕЙ. Подробнее см. в Стандартной
общественной лицензии GNU.
Вы должны были получить копию Стандартной общественной лицензии GNU
вместе с этой программой. Если это не так, см.
<https://www.gnu.org/licenses/>.
*/
package ru.malik.elaborarer.avtoo.generator;
import avt.lang.array.*;
import ru.malik.elaborarer.avtoo.lang.*;
public class AssemblerElementWriter(Object, AVTOOConstants)
{
/*<fold флаги формирования сигнатуры типа>*/
public static final int NORM = 0;
public static final int WEAK = 1;
public static final int STACK = 2;
/*</fold>*/
protected int fldOffset;
protected char[] fldText;
public () { }
public void trim() { fldText.length = fldOffset; }
public char[] get() {
char[] result = fldText;
result.length = fldOffset;
return result;
}
public AssemblerElementWriter set(char[] text, int offset) {
fldText = text;
fldOffset = offset;
text.length = text.capacity;
return this;
}
public AssemblerElementWriter writeChar(char character) {
int offset = fldOffset;
fldText[offset++] = character;
fldOffset = offset;
return this;
}
public AssemblerElementWriter writeLabel(char character, int label) {
int length = 7;
if(label >= 0x00010000 && label < 0x01000000)
{
length = 9;
}
else if(label >= 0x01000000 || label < 0x00000000)
{
length = 11;
}
int offset = fldOffset;
for(char[] text = fldText, text[offset] = text[offset + 2] = '.', text[offset + 1] = character, offset += 3, int index = 3; index < length; index++)
{
text[offset++] = Char.toUpperCase(Char.toChar((label >> (length - index - 1 << 2)) & 0x0f));
}
fldOffset = offset;
return this;
}
public AssemblerElementWriter writeLabel(int label) {
int length = 7;
if(label >= 0x00010000 && label < 0x01000000)
{
length = 9;
}
else if(label >= 0x01000000 || label < 0x00000000)
{
length = 11;
}
int offset = fldOffset;
for(char[] text = fldText, text[offset++] = '.', text[offset++] = text[offset + length - 3] = '$', int index = 3; index < length; index++)
{
text[offset++] = Char.toChar((label >> (length - index - 1 << 2)) & 0x0f);
}
fldOffset = offset + 1;
return this;
}
public AssemblerElementWriter writeOffset(int value) {
int length = 2;
if(value >= 0x00000010 && value < 0x00000100)
{
length = 3;
}
else if(value >= 0x00000100 && value < 0x00001000)
{
length = 4;
}
else if(value >= 0x00001000 && value < 0x00010000)
{
length = 5;
}
else if(value >= 0x00010000 && value < 0x00100000)
{
length = 6;
}
else if(value >= 0x00100000 && value < 0x01000000)
{
length = 7;
}
else if(value >= 0x01000000 && value < 0x10000000)
{
length = 8;
}
else if(value >= 0x10000010 || value < 0x00000000)
{
length = 9;
}
int offset = fldOffset;
for(char[] text = fldText, text[offset++] = '$', int index = 1; index < length; index++)
{
text[offset++] = Char.toChar((int) (value >> (length - index - 1 << 2)) & 0x0f);
}
fldOffset = offset;
return this;
}
public AssemblerElementWriter writeByte(int value) {
int offset = fldOffset;
for(char[] text = fldText, text[offset++] = '$', int index = 1; index < 3; index++)
{
text[offset++] = Char.toChar((int) (value >> (2 - index << 2)) & 0x0f);
}
fldOffset = offset;
return this;
}
public AssemblerElementWriter writeShort(int value) {
int offset = fldOffset;
for(char[] text = fldText, text[offset++] = '$', int index = 1; index < 5; index++)
{
text[offset++] = Char.toChar((int) (value >> (4 - index << 2)) & 0x0f);
}
fldOffset = offset;
return this;
}
public AssemblerElementWriter writeInt(int value) {
int offset = fldOffset;
for(char[] text = fldText, text[offset++] = '$', int index = 1; index < 9; index++)
{
text[offset++] = Char.toChar((int) (value >> (8 - index << 2)) & 0x0f);
}
fldOffset = offset;
return this;
}
public AssemblerElementWriter writeLong(long value) {
int offset = fldOffset;
for(char[] text = fldText, text[offset++] = '$', int index = 1; index < 17; index++)
{
text[offset++] = Char.toChar((int) (value >> (16 - index << 2)) & 0x0f);
}
fldOffset = offset;
return this;
}
public AssemblerElementWriter writeDecimal(int value) {
int offset = fldOffset;
char[] text = fldText;
if(value >= 0)
{
value = -value;
} else
{
text[offset++] = '-';
}
int length = -1;
if(value > -100 && value <= -10)
{
length = -2;
}
else if(value > -1000 && value <= -100)
{
length = -3;
}
else if(value > -10000 && value <= -1000)
{
length = -4;
}
else if(value > -100000 && value <= -10000)
{
length = -5;
}
else if(value > -1000000 && value <= -100000)
{
length = -6;
}
else if(value > -10000000 && value <= -1000000)
{
length = -7;
}
else if(value > -100000000 && value <= -10000000)
{
length = -8;
}
else if(value > -1000000000 && value <= -100000000)
{
length = -9;
}
else if(value <= -1000000000)
{
length = -10;
}
for(offset -= length, int index = 0; index-- > length; value /= 10)
{
text[offset + index] = (char) ('0' - value % 10);
}
fldOffset = offset;
return this;
}
public AssemblerElementWriter writeString(CharSequence string) {
int offset = fldOffset;
string.copyInto(fldText, offset);
fldOffset = offset + string.length;
return this;
}
public AssemblerElementWriter writeString(CharSequence string, int beginIndex, int endIndex) {
int offset = fldOffset;
string.getChars(beginIndex, endIndex, fldText, offset);
fldOffset = offset - beginIndex + endIndex;
return this;
}
public AssemblerElementWriter writeLabel(Node node) {
int label = node.debugIndex;
return label >= 0 ? writeLabel('D', label) : writeLabel('L', node.labelIndex);
}
public AssemblerElementWriter writeSignature(int kind, int flags) {
String signature;
switch(kind)
{
case REF:
signature = (flags & WEAK) != 0 ? "w" : "r";
break;
case BOOLEAN:
signature = (flags & STACK) != 0 ? "i" : "b";
break;
case CHAR:
signature = (flags & STACK) != 0 ? "i" : "c";
break;
case REAL:
signature = "e";
break;
case DOUBLE:
signature = "d";
break;
case DOUBLE2:
signature = "d2";
break;
case DOUBLE4:
signature = "d4";
break;
case DOUBLE8:
signature = "d8";
break;
case FLOAT:
signature = "f";
break;
case FLOAT2:
signature = "f2";
break;
case FLOAT4:
signature = "f4";
break;
case FLOAT8:
signature = "f8";
break;
case BYTE:
signature = (flags & STACK) != 0 ? "i" : "b";
break;
case BYTE2:
signature = "b2";
break;
case BYTE4:
signature = "b4";
break;
case BYTE8:
signature = "b8";
break;
case SHORT:
signature = (flags & STACK) != 0 ? "i" : "s";
break;
case SHORT2:
signature = "s2";
break;
case SHORT4:
signature = "s4";
break;
case SHORT8:
signature = "s8";
break;
case INT:
signature = "i";
break;
case INT2:
signature = "i2";
break;
case INT4:
signature = "i4";
break;
case INT8:
signature = "i8";
break;
case LONG:
signature = "l";
break;
case LONG2:
signature = "l2";
break;
case LONG4:
signature = "l4";
break;
case LONG8:
signature = "l8";
break;
default:
signature = "";
}
return writeString(signature);
}
public AssemblerElementWriter writeSignature(Type type, int flags) {
String signature;
switch(type.kind)
{
case REF:
signature = (flags & WEAK) != 0 ? "w" : "r";
break;
case BOOLEAN:
signature = (flags & STACK) != 0 ? "i" : "b";
break;
case CHAR:
signature = (flags & STACK) != 0 ? "i" : "c";
break;
case REAL:
signature = "e";
break;
case DOUBLE:
signature = "d";
break;
case DOUBLE2:
signature = "d2";
break;
case DOUBLE4:
signature = "d4";
break;
case DOUBLE8:
signature = "d8";
break;
case FLOAT:
signature = "f";
break;
case FLOAT2:
signature = "f2";
break;
case FLOAT4:
signature = "f4";
break;
case FLOAT8:
signature = "f8";
break;
case BYTE:
signature = (flags & STACK) != 0 ? "i" : "b";
break;
case BYTE2:
signature = "b2";
break;
case BYTE4:
signature = "b4";
break;
case BYTE8:
signature = "b8";
break;
case SHORT:
signature = (flags & STACK) != 0 ? "i" : "s";
break;
case SHORT2:
signature = "s2";
break;
case SHORT4:
signature = "s4";
break;
case SHORT8:
signature = "s8";
break;
case INT:
signature = "i";
break;
case INT2:
signature = "i2";
break;
case INT4:
signature = "i4";
break;
case INT8:
signature = "i8";
break;
case LONG:
signature = "l";
break;
case LONG2:
signature = "l2";
break;
case LONG4:
signature = "l4";
break;
case LONG8:
signature = "l8";
break;
default:
signature = "";
}
return writeString(signature);
}
public final AssemblerElementWriter set(char[] dst) { return set(dst, 0); }
public final int offset { read = fldOffset, write = fldOffset }
}