2273 lines
59 KiB
C++
2273 lines
59 KiB
C++
#include "InterCodeGenerator.h"
|
|
#include <crtdbg.h>
|
|
|
|
InterCodeGenerator::InterCodeGenerator(Errors* errors)
|
|
: mErrors(errors), mForceNativeCode(false)
|
|
{
|
|
|
|
}
|
|
|
|
InterCodeGenerator::~InterCodeGenerator(void)
|
|
{
|
|
|
|
}
|
|
|
|
static inline InterType InterTypeOf(const Declaration* dec)
|
|
{
|
|
switch (dec->mType)
|
|
{
|
|
default:
|
|
case DT_TYPE_VOID:
|
|
return IT_NONE;
|
|
case DT_TYPE_INTEGER:
|
|
case DT_TYPE_ENUM:
|
|
return (dec->mFlags & DTF_SIGNED) ? IT_SIGNED : IT_UNSIGNED;
|
|
case DT_TYPE_BOOL:
|
|
return IT_BOOL;
|
|
case DT_TYPE_FLOAT:
|
|
return IT_FLOAT;
|
|
case DT_TYPE_POINTER:
|
|
case DT_TYPE_FUNCTION:
|
|
case DT_TYPE_ARRAY:
|
|
return IT_POINTER;
|
|
}
|
|
}
|
|
|
|
InterCodeGenerator::ExValue InterCodeGenerator::Dereference(InterCodeProcedure* proc, InterCodeBasicBlock*& block, ExValue v, int level)
|
|
{
|
|
while (v.mReference > level)
|
|
{
|
|
InterInstruction ins;
|
|
ins.mCode = IC_LOAD;
|
|
ins.mMemory = IM_INDIRECT;
|
|
ins.mSType[0] = IT_POINTER;
|
|
ins.mSTemp[0] = v.mTemp;
|
|
ins.mTType = v.mReference == 1 ? InterTypeOf(v.mType) : IT_POINTER;
|
|
ins.mTTemp = proc->AddTemporary(ins.mTType);
|
|
ins.mOperandSize = v.mReference == 1 ? v.mType->mSize : 2;
|
|
block->Append(ins);
|
|
|
|
v = ExValue(v.mType, ins.mTTemp, v.mReference - 1);
|
|
}
|
|
|
|
return v;
|
|
}
|
|
|
|
InterCodeGenerator::ExValue InterCodeGenerator::CoerceType(InterCodeProcedure* proc, InterCodeBasicBlock*& block, ExValue v, Declaration* type)
|
|
{
|
|
if (v.mType->IsIntegerType() && type->mType == DT_TYPE_FLOAT)
|
|
{
|
|
InterInstruction cins;
|
|
cins.mCode = IC_CONVERSION_OPERATOR;
|
|
cins.mOperator = IA_INT2FLOAT;
|
|
cins.mSType[0] = InterTypeOf(v.mType);
|
|
cins.mSTemp[0] = v.mTemp;
|
|
cins.mTType = IT_FLOAT;
|
|
cins.mTTemp = proc->AddTemporary(cins.mTType);
|
|
v.mTemp = cins.mTTemp;
|
|
v.mType = type;
|
|
block->Append(cins);
|
|
}
|
|
else if (v.mType->mType == DT_TYPE_FLOAT && type->IsIntegerType())
|
|
{
|
|
InterInstruction cins;
|
|
cins.mCode = IC_CONVERSION_OPERATOR;
|
|
cins.mOperator = IA_FLOAT2INT;
|
|
cins.mSType[0] = InterTypeOf(v.mType);
|
|
cins.mSTemp[0] = v.mTemp;
|
|
cins.mTType = InterTypeOf(type);
|
|
cins.mTTemp = proc->AddTemporary(cins.mTType);
|
|
v.mTemp = cins.mTTemp;
|
|
v.mType = type;
|
|
block->Append(cins);
|
|
}
|
|
|
|
return v;
|
|
}
|
|
|
|
static inline bool InterTypeTypeInteger(InterType t)
|
|
{
|
|
return t == IT_UNSIGNED || t == IT_SIGNED || t == IT_BOOL;
|
|
}
|
|
|
|
static inline InterType InterTypeOfArithmetic(InterType t1, InterType t2)
|
|
{
|
|
if (t1 == IT_FLOAT || t2 == IT_FLOAT)
|
|
return IT_FLOAT;
|
|
else if (t1 == IT_SIGNED && t2 == IT_SIGNED)
|
|
return IT_SIGNED;
|
|
else if (t1 == IT_POINTER && t2 == IT_POINTER)
|
|
return IT_SIGNED;
|
|
else if (t1 == IT_POINTER || t2 == IT_POINTER)
|
|
return IT_POINTER;
|
|
else
|
|
return IT_UNSIGNED;
|
|
}
|
|
|
|
void InterCodeGenerator::InitGlobalVariable(InterCodeModule * mod, Declaration* dec)
|
|
{
|
|
if (dec->mVarIndex < 0)
|
|
{
|
|
InterVariable var;
|
|
var.mOffset = 0;
|
|
var.mSize = dec->mSize;
|
|
var.mData = nullptr;
|
|
var.mIdent = dec->mIdent;
|
|
if (dec->mValue)
|
|
{
|
|
if (dec->mValue->mType == EX_CONSTANT)
|
|
{
|
|
uint8* d = new uint8[dec->mSize];
|
|
memset(d, 0, dec->mSize);
|
|
var.mData = d;
|
|
|
|
GrowingArray<InterVariable::Reference> references({ 0 });
|
|
BuildInitializer(mod, d, 0, dec->mValue->mDecValue, references);
|
|
var.mNumReferences = references.Size();
|
|
if (var.mNumReferences)
|
|
{
|
|
var.mReferences = new InterVariable::Reference[var.mNumReferences];
|
|
for (int i = 0; i < var.mNumReferences; i++)
|
|
var.mReferences[i] = references[i];
|
|
}
|
|
}
|
|
else
|
|
mErrors->Error(dec->mLocation, "Non constant initializer");
|
|
}
|
|
dec->mVarIndex = mod->mGlobalVars.Size();
|
|
var.mIndex = dec->mVarIndex;
|
|
mod->mGlobalVars.Push(var);
|
|
}
|
|
}
|
|
|
|
void InterCodeGenerator::TranslateAssembler(InterCodeModule* mod, Expression * exp)
|
|
{
|
|
int offset = 0, osize = 0;
|
|
Expression* cexp = exp;
|
|
while (cexp)
|
|
{
|
|
osize += AsmInsSize(cexp->mAsmInsType, cexp->mAsmInsMode);
|
|
cexp = cexp->mRight;
|
|
}
|
|
|
|
InterVariable var;
|
|
var.mOffset = 0;
|
|
var.mSize = osize;
|
|
uint8* d = new uint8[osize];
|
|
var.mData = d;
|
|
var.mAssembler = true;
|
|
|
|
var.mIndex = mod->mGlobalVars.Size();
|
|
if (exp->mDecValue)
|
|
{
|
|
exp->mDecValue->mVarIndex = var.mIndex;
|
|
var.mIdent = exp->mDecValue->mIdent;
|
|
}
|
|
mod->mGlobalVars.Push(var);
|
|
|
|
GrowingArray<InterVariable::Reference> references({ 0 });
|
|
|
|
cexp = exp;
|
|
while (cexp)
|
|
{
|
|
if (cexp->mAsmInsType != ASMIT_BYTE)
|
|
{
|
|
int opcode = AsmInsOpcodes[cexp->mAsmInsType][cexp->mAsmInsMode];
|
|
d[offset++] = opcode;
|
|
}
|
|
|
|
Declaration* aexp = nullptr;
|
|
if (cexp->mLeft)
|
|
aexp = cexp->mLeft->mDecValue;
|
|
|
|
switch (cexp->mAsmInsMode)
|
|
{
|
|
case ASMIM_IMPLIED:
|
|
break;
|
|
case ASMIM_IMMEDIATE:
|
|
if (aexp->mType == DT_CONST_INTEGER)
|
|
d[offset++] = cexp->mLeft->mDecValue->mInteger & 255;
|
|
else if (aexp->mType == DT_LABEL_REF)
|
|
{
|
|
if (aexp->mBase->mBase->mVarIndex < 0)
|
|
TranslateAssembler(mod, aexp->mBase->mBase->mValue);
|
|
|
|
InterVariable::Reference ref;
|
|
ref.mFunction = false;
|
|
ref.mUpper = aexp->mFlags & DTF_UPPER_BYTE;
|
|
ref.mLower = !(aexp->mFlags & DTF_UPPER_BYTE);
|
|
ref.mAddr = offset;
|
|
ref.mIndex = aexp->mBase->mBase->mVarIndex;
|
|
ref.mOffset = aexp->mOffset + aexp->mBase->mInteger;
|
|
|
|
references.Push(ref);
|
|
|
|
offset += 1;
|
|
}
|
|
break;
|
|
case ASMIM_ZERO_PAGE:
|
|
case ASMIM_ZERO_PAGE_X:
|
|
case ASMIM_INDIRECT_X:
|
|
case ASMIM_INDIRECT_Y:
|
|
d[offset++] = aexp->mInteger;
|
|
break;
|
|
case ASMIM_ABSOLUTE:
|
|
case ASMIM_INDIRECT:
|
|
case ASMIM_ABSOLUTE_X:
|
|
case ASMIM_ABSOLUTE_Y:
|
|
if (aexp->mType == DT_CONST_INTEGER)
|
|
{
|
|
d[offset++] = cexp->mLeft->mDecValue->mInteger & 255;
|
|
d[offset++] = cexp->mLeft->mDecValue->mInteger >> 8;
|
|
}
|
|
else if (aexp->mType == DT_LABEL)
|
|
{
|
|
if (aexp->mBase->mVarIndex < 0)
|
|
TranslateAssembler(mod, aexp->mBase->mValue);
|
|
|
|
InterVariable::Reference ref;
|
|
ref.mFunction = false;
|
|
ref.mUpper = true;
|
|
ref.mLower = true;
|
|
ref.mAddr = offset;
|
|
ref.mIndex = aexp->mBase->mVarIndex;
|
|
ref.mOffset = aexp->mInteger;
|
|
|
|
references.Push(ref);
|
|
|
|
offset += 2;
|
|
}
|
|
else if (aexp->mType == DT_LABEL_REF)
|
|
{
|
|
if (aexp->mBase->mBase->mVarIndex < 0)
|
|
TranslateAssembler(mod, aexp->mBase->mBase->mValue);
|
|
|
|
InterVariable::Reference ref;
|
|
ref.mFunction = false;
|
|
ref.mUpper = true;
|
|
ref.mLower = true;
|
|
ref.mAddr = offset;
|
|
ref.mIndex = aexp->mBase->mBase->mVarIndex;
|
|
ref.mOffset = aexp->mOffset + aexp->mBase->mInteger;
|
|
|
|
references.Push(ref);
|
|
|
|
offset += 2;
|
|
}
|
|
else if (aexp->mType == DT_CONST_ASSEMBLER)
|
|
{
|
|
if (aexp->mVarIndex < 0)
|
|
TranslateAssembler(mod, aexp->mValue);
|
|
|
|
InterVariable::Reference ref;
|
|
ref.mFunction = false;
|
|
ref.mUpper = true;
|
|
ref.mLower = true;
|
|
ref.mAddr = offset;
|
|
ref.mIndex = aexp->mVarIndex;
|
|
ref.mOffset = 0;
|
|
|
|
references.Push(ref);
|
|
|
|
offset += 2;
|
|
}
|
|
else if (aexp->mType == DT_VARIABLE)
|
|
{
|
|
if (aexp->mFlags & DTF_GLOBAL)
|
|
{
|
|
InitGlobalVariable(mod, aexp);
|
|
|
|
InterVariable::Reference ref;
|
|
ref.mFunction = false;
|
|
ref.mUpper = true;
|
|
ref.mLower = true;
|
|
ref.mAddr = offset;
|
|
ref.mIndex = aexp->mVarIndex;
|
|
ref.mOffset = 0;
|
|
|
|
references.Push(ref);
|
|
|
|
offset += 2;
|
|
}
|
|
}
|
|
else if (aexp->mType == DT_VARIABLE_REF)
|
|
{
|
|
if (aexp->mBase->mFlags & DTF_GLOBAL)
|
|
{
|
|
InitGlobalVariable(mod, aexp->mBase);
|
|
|
|
InterVariable::Reference ref;
|
|
ref.mFunction = false;
|
|
ref.mUpper = true;
|
|
ref.mLower = true;
|
|
ref.mAddr = offset;
|
|
ref.mIndex = aexp->mBase->mVarIndex;
|
|
ref.mOffset = aexp->mOffset;
|
|
|
|
references.Push(ref);
|
|
|
|
offset += 2;
|
|
}
|
|
}
|
|
break;
|
|
case ASMIM_RELATIVE:
|
|
d[offset] = aexp->mInteger - offset - 1;
|
|
offset++;
|
|
break;
|
|
}
|
|
|
|
cexp = cexp->mRight;
|
|
}
|
|
|
|
assert(offset == osize);
|
|
|
|
InterVariable& ivar(mod->mGlobalVars[var.mIndex]);
|
|
|
|
ivar.mNumReferences = references.Size();
|
|
if (ivar.mNumReferences)
|
|
{
|
|
ivar.mReferences = new InterVariable::Reference[ivar.mNumReferences];
|
|
for (int i = 0; i < ivar.mNumReferences; i++)
|
|
ivar.mReferences[i] = references[i];
|
|
}
|
|
}
|
|
|
|
InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* procType, InterCodeProcedure* proc, InterCodeBasicBlock*& block, Expression* exp, InterCodeBasicBlock* breakBlock, InterCodeBasicBlock* continueBlock)
|
|
{
|
|
Declaration* dec;
|
|
ExValue vl, vr;
|
|
|
|
for (;;)
|
|
{
|
|
switch (exp->mType)
|
|
{
|
|
case EX_VOID:
|
|
return ExValue(TheVoidTypeDeclaration);
|
|
|
|
case EX_SEQUENCE:
|
|
vr = TranslateExpression(procType, proc, block, exp->mLeft, breakBlock, continueBlock);
|
|
exp = exp->mRight;
|
|
if (!exp)
|
|
return ExValue(TheVoidTypeDeclaration);
|
|
break;
|
|
case EX_CONSTANT:
|
|
dec = exp->mDecValue;
|
|
switch (dec->mType)
|
|
{
|
|
case DT_CONST_INTEGER:
|
|
{
|
|
InterInstruction ins;
|
|
ins.mCode = IC_CONSTANT;
|
|
ins.mTType = InterTypeOf(dec->mBase);
|
|
ins.mTTemp = proc->AddTemporary(ins.mTType);
|
|
if (ins.mTType == IT_SIGNED)
|
|
{
|
|
if (dec->mInteger < -32768 || dec->mInteger > 32767)
|
|
mErrors->Warning(dec->mLocation, "Integer constant truncated");
|
|
ins.mIntValue = short(dec->mInteger);
|
|
}
|
|
else
|
|
{
|
|
if (dec->mInteger < 0 || dec->mInteger > 65535)
|
|
mErrors->Warning(dec->mLocation, "Unsigned integer constant truncated");
|
|
ins.mIntValue = unsigned short(dec->mInteger);
|
|
}
|
|
block->Append(ins);
|
|
return ExValue(dec->mBase, ins.mTTemp);
|
|
|
|
} break;
|
|
|
|
case DT_CONST_FLOAT:
|
|
{
|
|
InterInstruction ins;
|
|
ins.mCode = IC_CONSTANT;
|
|
ins.mTType = InterTypeOf(dec->mBase);
|
|
ins.mTTemp = proc->AddTemporary(ins.mTType);
|
|
ins.mFloatValue = dec->mNumber;
|
|
block->Append(ins);
|
|
return ExValue(dec->mBase, ins.mTTemp);
|
|
|
|
} break;
|
|
|
|
case DT_CONST_ADDRESS:
|
|
{
|
|
InterInstruction ins;
|
|
ins.mCode = IC_CONSTANT;
|
|
ins.mTType = IT_POINTER;
|
|
ins.mTTemp = proc->AddTemporary(IT_POINTER);
|
|
ins.mIntValue = dec->mInteger;
|
|
ins.mMemory = IM_ABSOLUTE;
|
|
block->Append(ins);
|
|
return ExValue(dec->mBase, ins.mTTemp);
|
|
|
|
} break;
|
|
|
|
case DT_CONST_FUNCTION:
|
|
{
|
|
if (dec->mVarIndex < 0)
|
|
{
|
|
InterCodeProcedure* cproc = this->TranslateProcedure(proc->mModule, dec->mValue, dec);
|
|
cproc->ReduceTemporaries();
|
|
}
|
|
|
|
InterInstruction ins;
|
|
ins.mCode = IC_CONSTANT;
|
|
ins.mTType = InterTypeOf(dec->mBase);
|
|
ins.mTTemp = proc->AddTemporary(ins.mTType);
|
|
ins.mVarIndex = dec->mVarIndex;
|
|
ins.mMemory = IM_PROCEDURE;
|
|
ins.mIntValue = 0;
|
|
block->Append(ins);
|
|
return ExValue(dec->mBase, ins.mTTemp);
|
|
|
|
} break;
|
|
|
|
case DT_CONST_POINTER:
|
|
{
|
|
vl = TranslateExpression(procType, proc, block, dec->mValue, breakBlock, continueBlock);
|
|
return vl;
|
|
}
|
|
case DT_CONST_DATA:
|
|
{
|
|
if (dec->mVarIndex < 0)
|
|
{
|
|
dec->mVarIndex = proc->mModule->mGlobalVars.Size();
|
|
InterVariable var;
|
|
var.mIndex = dec->mVarIndex;
|
|
var.mIdent = dec->mIdent;
|
|
var.mOffset = 0;
|
|
var.mSize = dec->mSize;
|
|
var.mData = dec->mData;
|
|
proc->mModule->mGlobalVars.Push(var);
|
|
}
|
|
|
|
InterInstruction ins;
|
|
ins.mCode = IC_CONSTANT;
|
|
ins.mTType = IT_POINTER;
|
|
ins.mTTemp = proc->AddTemporary(IT_POINTER);
|
|
ins.mIntValue = 0;
|
|
ins.mVarIndex = dec->mVarIndex;
|
|
ins.mMemory = IM_GLOBAL;
|
|
block->Append(ins);
|
|
return ExValue(dec->mBase, ins.mTTemp, 1);
|
|
}
|
|
|
|
case DT_CONST_STRUCT:
|
|
{
|
|
if (dec->mVarIndex < 0)
|
|
{
|
|
InterVariable var;
|
|
var.mOffset = 0;
|
|
var.mSize = dec->mSize;
|
|
var.mData = nullptr;
|
|
var.mIdent = dec->mIdent;
|
|
|
|
uint8* d = new uint8[dec->mSize];
|
|
memset(d, 0, dec->mSize);
|
|
var.mData = d;
|
|
|
|
GrowingArray<InterVariable::Reference> references({ 0 });
|
|
BuildInitializer(proc->mModule, d, 0, dec, references);
|
|
var.mNumReferences = references.Size();
|
|
if (var.mNumReferences)
|
|
{
|
|
var.mReferences = new InterVariable::Reference[var.mNumReferences];
|
|
for (int i = 0; i < var.mNumReferences; i++)
|
|
var.mReferences[i] = references[i];
|
|
}
|
|
|
|
dec->mVarIndex = proc->mModule->mGlobalVars.Size();
|
|
var.mIndex = dec->mVarIndex;
|
|
proc->mModule->mGlobalVars.Push(var);
|
|
}
|
|
|
|
InterInstruction ins;
|
|
ins.mCode = IC_CONSTANT;
|
|
ins.mTType = IT_POINTER;
|
|
ins.mTTemp = proc->AddTemporary(IT_POINTER);
|
|
ins.mIntValue = 0;
|
|
ins.mVarIndex = dec->mVarIndex;
|
|
ins.mMemory = IM_GLOBAL;
|
|
block->Append(ins);
|
|
return ExValue(dec->mBase, ins.mTTemp, 1);
|
|
}
|
|
|
|
default:
|
|
mErrors->Error(dec->mLocation, "Unimplemented constant type");
|
|
}
|
|
|
|
return ExValue(TheVoidTypeDeclaration);
|
|
|
|
case EX_VARIABLE:
|
|
{
|
|
dec = exp->mDecValue;
|
|
|
|
InterInstruction ins;
|
|
ins.mCode = IC_CONSTANT;
|
|
ins.mTType = IT_POINTER;
|
|
ins.mTTemp = proc->AddTemporary(ins.mTType);
|
|
ins.mOperandSize = dec->mSize;
|
|
ins.mIntValue = dec->mOffset;
|
|
if (dec->mType == DT_ARGUMENT)
|
|
ins.mMemory = IM_PARAM;
|
|
else if (dec->mFlags & DTF_GLOBAL)
|
|
{
|
|
InitGlobalVariable(proc->mModule, dec);
|
|
ins.mMemory = IM_GLOBAL;
|
|
}
|
|
else
|
|
ins.mMemory = IM_LOCAL;
|
|
ins.mVarIndex = dec->mVarIndex;
|
|
|
|
block->Append(ins);
|
|
|
|
if (!(dec->mBase->mFlags & DTF_DEFINED))
|
|
mErrors->Error(dec->mLocation, "Undefined variable type");
|
|
|
|
return ExValue(dec->mBase, ins.mTTemp, 1);
|
|
}
|
|
|
|
|
|
case EX_ASSIGNMENT:
|
|
{
|
|
vr = TranslateExpression(procType, proc, block, exp->mRight, breakBlock, continueBlock);
|
|
vl = TranslateExpression(procType, proc, block, exp->mLeft, breakBlock, continueBlock);
|
|
|
|
if (!vl.mType->CanAssign(vr.mType))
|
|
mErrors->Error(exp->mLocation, "Cannot assign incompatible types");
|
|
|
|
if (vl.mType->mFlags & DTF_CONST)
|
|
mErrors->Error(exp->mLocation, "Cannot assign to const type");
|
|
|
|
if (vl.mType->mType == DT_TYPE_STRUCT || vl.mType->mType == DT_TYPE_ARRAY || vl.mType->mType == DT_TYPE_UNION)
|
|
{
|
|
vr = Dereference(proc, block, vr, 1);
|
|
vl = Dereference(proc, block, vl, 1);
|
|
|
|
if (vl.mReference != 1)
|
|
mErrors->Error(exp->mLeft->mLocation, "Not a left hand expression");
|
|
if (vr.mReference != 1)
|
|
mErrors->Error(exp->mLeft->mLocation, "Not an adressable expression");
|
|
|
|
|
|
InterInstruction ins;
|
|
ins.mCode = IC_COPY;
|
|
ins.mMemory = IM_INDIRECT;
|
|
ins.mSType[0] = IT_POINTER;
|
|
ins.mSTemp[0] = vr.mTemp;
|
|
ins.mSType[1] = IT_POINTER;
|
|
ins.mSTemp[1] = vl.mTemp;
|
|
ins.mOperandSize = vl.mType->mSize;
|
|
block->Append(ins);
|
|
}
|
|
else
|
|
{
|
|
if (vl.mType->mType == DT_TYPE_POINTER && (vr.mType->mType == DT_TYPE_ARRAY || vr.mType->mType == DT_TYPE_FUNCTION))
|
|
vr = Dereference(proc, block, vr, 1);
|
|
else
|
|
vr = Dereference(proc, block, vr);
|
|
|
|
vl = Dereference(proc, block, vl, 1);
|
|
|
|
if (vl.mReference != 1)
|
|
mErrors->Error(exp->mLeft->mLocation, "Not a left hand expression");
|
|
|
|
InterInstruction ins;
|
|
|
|
if (exp->mToken != TK_ASSIGN)
|
|
{
|
|
ExValue vll = Dereference(proc, block, vl);
|
|
|
|
if (vl.mType->mType == DT_TYPE_POINTER)
|
|
{
|
|
InterInstruction cins;
|
|
cins.mCode = IC_CONSTANT;
|
|
|
|
if (exp->mToken == TK_ASSIGN_ADD)
|
|
{
|
|
cins.mIntValue = vl.mType->mBase->mSize;
|
|
}
|
|
else if (exp->mToken == TK_ASSIGN_SUB)
|
|
{
|
|
cins.mIntValue = -vl.mType->mBase->mSize;
|
|
}
|
|
else
|
|
mErrors->Error(exp->mLocation, "Invalid pointer assignment");
|
|
|
|
if (!vr.mType->IsIntegerType())
|
|
mErrors->Error(exp->mLocation, "Invalid argument for pointer inc/dec");
|
|
|
|
cins.mTType = IT_SIGNED;
|
|
cins.mTTemp = proc->AddTemporary(cins.mTType);
|
|
block->Append(cins);
|
|
|
|
InterInstruction mins;
|
|
mins.mCode = IC_BINARY_OPERATOR;
|
|
mins.mOperator = IA_MUL;
|
|
mins.mSType[0] = IT_SIGNED;
|
|
mins.mSTemp[0] = vr.mTemp;
|
|
mins.mSType[1] = IT_SIGNED;
|
|
mins.mSTemp[1] = cins.mTTemp;
|
|
mins.mTType = IT_SIGNED;
|
|
mins.mTTemp = proc->AddTemporary(mins.mTType);
|
|
block->Append(mins);
|
|
|
|
InterInstruction ains;
|
|
ains.mCode = IC_LEA;
|
|
ains.mMemory = IM_INDIRECT;
|
|
ains.mSType[0] = IT_SIGNED;
|
|
ains.mSTemp[0] = mins.mTTemp;
|
|
ains.mSType[1] = IT_POINTER;
|
|
ains.mSTemp[1] = vl.mTemp;
|
|
ains.mTType = IT_POINTER;
|
|
ains.mTTemp = proc->AddTemporary(ains.mTType);
|
|
block->Append(ains);
|
|
}
|
|
else
|
|
{
|
|
vr = CoerceType(proc, block, vr, vll.mType);
|
|
|
|
InterInstruction oins;
|
|
oins.mCode = IC_BINARY_OPERATOR;
|
|
oins.mSType[0] = InterTypeOf(vr.mType);
|
|
oins.mSTemp[0] = vr.mTemp;
|
|
oins.mSType[1] = InterTypeOf(vll.mType);
|
|
oins.mSTemp[1] = vll.mTemp;
|
|
oins.mTType = InterTypeOf(vll.mType);
|
|
oins.mTTemp = proc->AddTemporary(oins.mTType);
|
|
|
|
if (!vll.mType->IsNumericType())
|
|
mErrors->Error(exp->mLocation, "Left hand element type is not numeric");
|
|
if (!vr.mType->IsNumericType())
|
|
mErrors->Error(exp->mLocation, "Right hand element type is not numeric");
|
|
|
|
switch (exp->mToken)
|
|
{
|
|
case TK_ASSIGN_ADD:
|
|
oins.mOperator = IA_ADD;
|
|
break;
|
|
case TK_ASSIGN_SUB:
|
|
oins.mOperator = IA_SUB;
|
|
break;
|
|
case TK_ASSIGN_MUL:
|
|
oins.mOperator = IA_MUL;
|
|
break;
|
|
case TK_ASSIGN_DIV:
|
|
if (vll.mType->mFlags & DTF_SIGNED)
|
|
oins.mOperator = IA_DIVS;
|
|
else
|
|
oins.mOperator = IA_DIVU;
|
|
break;
|
|
case TK_ASSIGN_MOD:
|
|
if (vll.mType->mFlags & DTF_SIGNED)
|
|
oins.mOperator = IA_MODS;
|
|
else
|
|
oins.mOperator = IA_MODU;
|
|
break;
|
|
case TK_ASSIGN_SHL:
|
|
oins.mOperator = IA_SHL;
|
|
break;
|
|
case TK_ASSIGN_SHR:
|
|
if (vll.mType->mFlags & DTF_SIGNED)
|
|
oins.mOperator = IA_SAR;
|
|
else
|
|
oins.mOperator = IA_SHR;
|
|
break;
|
|
case TK_ASSIGN_AND:
|
|
oins.mOperator = IA_AND;
|
|
break;
|
|
case TK_ASSIGN_XOR:
|
|
oins.mOperator = IA_XOR;
|
|
break;
|
|
case TK_ASSIGN_OR:
|
|
oins.mOperator = IA_OR;
|
|
break;
|
|
}
|
|
|
|
vr.mTemp = oins.mTTemp;
|
|
vr.mType = vll.mType;
|
|
|
|
block->Append(oins);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (vl.mType->IsIntegerType() && vr.mType->mType == DT_TYPE_FLOAT)
|
|
{
|
|
InterInstruction cins;
|
|
cins.mCode = IC_CONVERSION_OPERATOR;
|
|
cins.mOperator = IA_FLOAT2INT;
|
|
cins.mSType[0] = InterTypeOf(vr.mType);
|
|
cins.mSTemp[0] = vr.mTemp;
|
|
cins.mTType = InterTypeOf(vl.mType);
|
|
cins.mTTemp = proc->AddTemporary(cins.mTType);
|
|
vr.mTemp = cins.mTTemp;
|
|
vr.mType = TheSignedIntTypeDeclaration;
|
|
block->Append(cins);
|
|
}
|
|
else if (vl.mType->mType == DT_TYPE_FLOAT && vr.mType->IsIntegerType())
|
|
{
|
|
InterInstruction cins;
|
|
cins.mCode = IC_CONVERSION_OPERATOR;
|
|
cins.mOperator = IA_INT2FLOAT;
|
|
cins.mSType[0] = InterTypeOf(vr.mType);
|
|
cins.mSTemp[0] = vr.mTemp;
|
|
cins.mTType = InterTypeOf(vl.mType);;
|
|
cins.mTTemp = proc->AddTemporary(cins.mTType);
|
|
vr.mTemp = cins.mTTemp;
|
|
vr.mType = TheFloatTypeDeclaration;
|
|
block->Append(cins);
|
|
}
|
|
}
|
|
|
|
ins.mCode = IC_STORE;
|
|
ins.mMemory = IM_INDIRECT;
|
|
ins.mSType[0] = InterTypeOf(vr.mType);
|
|
ins.mSTemp[0] = vr.mTemp;
|
|
ins.mSType[1] = IT_POINTER;
|
|
ins.mSTemp[1] = vl.mTemp;
|
|
ins.mOperandSize = vl.mType->mSize;
|
|
block->Append(ins);
|
|
}
|
|
}
|
|
|
|
return vr;
|
|
|
|
case EX_INDEX:
|
|
{
|
|
vl = TranslateExpression(procType, proc, block, exp->mLeft, breakBlock, continueBlock);
|
|
vr = TranslateExpression(procType, proc, block, exp->mRight, breakBlock, continueBlock);
|
|
|
|
vl = Dereference(proc, block, vl, vl.mType->mType == DT_TYPE_POINTER ? 0 : 1);
|
|
vr = Dereference(proc, block, vr);
|
|
|
|
if (vl.mType->mType != DT_TYPE_ARRAY && vl.mType->mType != DT_TYPE_POINTER)
|
|
mErrors->Error(exp->mLocation, "Invalid type for indexing");
|
|
|
|
if (!vr.mType->IsIntegerType())
|
|
mErrors->Error(exp->mLocation, "Index operand is not integral number");
|
|
|
|
InterInstruction cins;
|
|
cins.mCode = IC_CONSTANT;
|
|
cins.mIntValue = vl.mType->mBase->mSize;
|
|
cins.mTType = IT_SIGNED;
|
|
cins.mTTemp = proc->AddTemporary(cins.mTType);
|
|
block->Append(cins);
|
|
|
|
InterInstruction mins;
|
|
mins.mCode = IC_BINARY_OPERATOR;
|
|
mins.mOperator = IA_MUL;
|
|
mins.mSType[0] = IT_SIGNED;
|
|
mins.mSTemp[0] = vr.mTemp;
|
|
mins.mSType[1] = IT_SIGNED;
|
|
mins.mSTemp[1] = cins.mTTemp;
|
|
mins.mTType = IT_SIGNED;
|
|
mins.mTTemp = proc->AddTemporary(mins.mTType);
|
|
block->Append(mins);
|
|
|
|
InterInstruction ains;
|
|
ains.mCode = IC_LEA;
|
|
ains.mMemory = IM_INDIRECT;
|
|
ains.mSType[0] = IT_SIGNED;
|
|
ains.mSTemp[0] = mins.mTTemp;
|
|
ains.mSType[1] = IT_POINTER;
|
|
ains.mSTemp[1] = vl.mTemp;
|
|
ains.mTType = IT_POINTER;
|
|
ains.mTTemp = proc->AddTemporary(ains.mTType);
|
|
block->Append(ains);
|
|
|
|
return ExValue(vl.mType->mBase, ains.mTTemp, 1);
|
|
}
|
|
|
|
case EX_QUALIFY:
|
|
{
|
|
vl = TranslateExpression(procType, proc, block, exp->mLeft, breakBlock, continueBlock);
|
|
vl = Dereference(proc, block, vl, 1);
|
|
|
|
if (vl.mReference != 1)
|
|
mErrors->Error(exp->mLocation, "Not an addressable expression");
|
|
|
|
InterInstruction cins;
|
|
cins.mCode = IC_CONSTANT;
|
|
cins.mIntValue = exp->mDecValue->mOffset;
|
|
cins.mTType = IT_SIGNED;
|
|
cins.mTTemp = proc->AddTemporary(cins.mTType);
|
|
block->Append(cins);
|
|
|
|
InterInstruction ains;
|
|
ains.mCode = IC_LEA;
|
|
ains.mMemory = IM_INDIRECT;
|
|
ains.mSType[0] = IT_SIGNED;
|
|
ains.mSTemp[0] = cins.mTTemp;
|
|
ains.mSType[1] = IT_POINTER;
|
|
ains.mSTemp[1] = vl.mTemp;
|
|
ains.mTType = IT_POINTER;
|
|
ains.mTTemp = proc->AddTemporary(ains.mTType);
|
|
block->Append(ains);
|
|
|
|
return ExValue(exp->mDecValue->mBase, ains.mTTemp, 1);
|
|
}
|
|
|
|
case EX_BINARY:
|
|
{
|
|
vl = TranslateExpression(procType, proc, block, exp->mLeft, breakBlock, continueBlock);
|
|
vr = TranslateExpression(procType, proc, block, exp->mRight, breakBlock, continueBlock);
|
|
vr = Dereference(proc, block, vr);
|
|
|
|
InterInstruction ins;
|
|
|
|
if (vl.mType->mType == DT_TYPE_POINTER || vl.mType->mType == DT_TYPE_ARRAY)
|
|
{
|
|
if (vl.mType->mType == DT_TYPE_POINTER)
|
|
vl = Dereference(proc, block, vl);
|
|
else
|
|
{
|
|
vl = Dereference(proc, block, vl, 1);
|
|
|
|
Declaration* ptype = new Declaration(exp->mLocation, DT_TYPE_POINTER);
|
|
ptype->mBase = vl.mType->mBase;
|
|
ptype->mSize = 2;
|
|
vl.mType = ptype;
|
|
}
|
|
|
|
if (vr.mType->IsIntegerType())
|
|
{
|
|
InterInstruction cins;
|
|
cins.mCode = IC_CONSTANT;
|
|
|
|
if (exp->mToken == TK_ADD)
|
|
{
|
|
cins.mIntValue = vl.mType->mBase->mSize;
|
|
}
|
|
else if (exp->mToken == TK_SUB)
|
|
{
|
|
cins.mIntValue = -vl.mType->mBase->mSize;
|
|
}
|
|
else
|
|
mErrors->Error(exp->mLocation, "Invalid pointer operation");
|
|
|
|
cins.mTType = IT_SIGNED;
|
|
cins.mTTemp = proc->AddTemporary(cins.mTType);
|
|
block->Append(cins);
|
|
|
|
InterInstruction mins;
|
|
mins.mCode = IC_BINARY_OPERATOR;
|
|
mins.mOperator = IA_MUL;
|
|
mins.mSType[0] = IT_SIGNED;
|
|
mins.mSTemp[0] = vr.mTemp;
|
|
mins.mSType[1] = IT_SIGNED;
|
|
mins.mSTemp[1] = cins.mTTemp;
|
|
mins.mTType = IT_SIGNED;
|
|
mins.mTTemp = proc->AddTemporary(mins.mTType);
|
|
block->Append(mins);
|
|
|
|
ins.mCode = IC_LEA;
|
|
ins.mMemory = IM_INDIRECT;
|
|
ins.mSType[0] = IT_SIGNED;
|
|
ins.mSTemp[0] = mins.mTTemp;
|
|
ins.mSType[1] = IT_POINTER;
|
|
ins.mSTemp[1] = vl.mTemp;
|
|
ins.mTType = IT_POINTER;
|
|
ins.mTTemp = proc->AddTemporary(ins.mTType);
|
|
block->Append(ins);
|
|
}
|
|
else if (vr.mType->IsSame(vl.mType))
|
|
{
|
|
if (exp->mToken == TK_SUB)
|
|
{
|
|
InterInstruction clins, crins;
|
|
clins.mCode = IC_TYPECAST;
|
|
clins.mSTemp[0] = vl.mTemp;
|
|
clins.mSType[0] = IT_POINTER;
|
|
clins.mTType = IT_SIGNED;
|
|
clins.mTTemp = proc->AddTemporary(clins.mTType);
|
|
block->Append(clins);
|
|
|
|
crins.mCode = IC_TYPECAST;
|
|
crins.mSTemp[0] = vr.mTemp;
|
|
crins.mSType[0] = IT_POINTER;
|
|
crins.mTType = IT_SIGNED;
|
|
crins.mTTemp = proc->AddTemporary(crins.mTType);
|
|
block->Append(crins);
|
|
|
|
InterInstruction cins;
|
|
cins.mCode = IC_CONSTANT;
|
|
cins.mIntValue = vl.mType->mBase->mSize;
|
|
cins.mTType = IT_SIGNED;
|
|
cins.mTTemp = proc->AddTemporary(cins.mTType);
|
|
block->Append(cins);
|
|
|
|
InterInstruction sins, dins;
|
|
sins.mCode = IC_BINARY_OPERATOR;
|
|
sins.mOperator = IA_SUB;
|
|
sins.mSType[0] = IT_SIGNED;
|
|
sins.mSTemp[0] = crins.mTTemp;
|
|
sins.mSType[1] = IT_SIGNED;
|
|
sins.mSTemp[1] = clins.mTTemp;
|
|
sins.mTType = IT_SIGNED;
|
|
sins.mTTemp = proc->AddTemporary(sins.mTType);
|
|
block->Append(sins);
|
|
|
|
dins.mCode = IC_BINARY_OPERATOR;
|
|
dins.mOperator = IA_DIVS;
|
|
dins.mSType[0] = IT_SIGNED;
|
|
dins.mSTemp[0] = cins.mTTemp;
|
|
dins.mSType[1] = IT_SIGNED;
|
|
dins.mSTemp[1] = sins.mTTemp;
|
|
dins.mTType = IT_SIGNED;
|
|
dins.mTTemp = proc->AddTemporary(dins.mTType);
|
|
block->Append(dins);
|
|
|
|
return ExValue(TheSignedIntTypeDeclaration, dins.mTTemp);
|
|
}
|
|
else
|
|
mErrors->Error(exp->mLocation, "Invalid pointer operation");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
vl = Dereference(proc, block, vl);
|
|
|
|
if (!vl.mType->IsNumericType())
|
|
mErrors->Error(exp->mLocation, "Left hand operand type is not numeric");
|
|
if (!vr.mType->IsNumericType())
|
|
mErrors->Error(exp->mLocation, "Right hand operand type is not numeric");
|
|
|
|
if (vl.mType->IsIntegerType() && vr.mType->mType == DT_TYPE_FLOAT)
|
|
{
|
|
InterInstruction cins;
|
|
cins.mCode = IC_CONVERSION_OPERATOR;
|
|
cins.mOperator = IA_INT2FLOAT;
|
|
cins.mSType[0] = InterTypeOf(vl.mType);
|
|
cins.mSTemp[0] = vl.mTemp;
|
|
cins.mTType = IT_FLOAT;
|
|
cins.mTTemp = proc->AddTemporary(cins.mTType);
|
|
vl.mTemp = cins.mTTemp;
|
|
vl.mType = TheFloatTypeDeclaration;
|
|
block->Append(cins);
|
|
}
|
|
else if (vl.mType->mType == DT_TYPE_FLOAT && vr.mType->IsIntegerType())
|
|
{
|
|
InterInstruction cins;
|
|
cins.mCode = IC_CONVERSION_OPERATOR;
|
|
cins.mOperator = IA_INT2FLOAT;
|
|
cins.mSType[0] = InterTypeOf(vr.mType);
|
|
cins.mSTemp[0] = vr.mTemp;
|
|
cins.mTType = IT_FLOAT;
|
|
cins.mTTemp = proc->AddTemporary(cins.mTType);
|
|
vr.mTemp = cins.mTTemp;
|
|
vr.mType = TheFloatTypeDeclaration;
|
|
block->Append(cins);
|
|
}
|
|
|
|
bool signedOP = (vl.mType->mFlags & DTF_SIGNED) && (vr.mType->mFlags & DTF_SIGNED);
|
|
|
|
ins.mCode = IC_BINARY_OPERATOR;
|
|
switch (exp->mToken)
|
|
{
|
|
case TK_ADD:
|
|
ins.mOperator = IA_ADD;
|
|
break;
|
|
case TK_SUB:
|
|
ins.mOperator = IA_SUB;
|
|
break;
|
|
case TK_MUL:
|
|
ins.mOperator = IA_MUL;
|
|
break;
|
|
case TK_DIV:
|
|
ins.mOperator = signedOP ? IA_DIVS : IA_DIVU;
|
|
break;
|
|
case TK_MOD:
|
|
ins.mOperator = signedOP ? IA_MODS : IA_MODU;
|
|
break;
|
|
case TK_LEFT_SHIFT:
|
|
ins.mOperator = IA_SHL;
|
|
break;
|
|
case TK_RIGHT_SHIFT:
|
|
ins.mOperator = (vl.mType->mFlags & DTF_SIGNED) ? IA_SAR : IA_SHR;
|
|
break;
|
|
case TK_BINARY_AND:
|
|
ins.mOperator = IA_AND;
|
|
break;
|
|
case TK_BINARY_OR:
|
|
ins.mOperator = IA_OR;
|
|
break;
|
|
case TK_BINARY_XOR:
|
|
ins.mOperator = IA_XOR;
|
|
break;
|
|
}
|
|
|
|
ins.mSType[0] = InterTypeOf(vr.mType);;
|
|
ins.mSTemp[0] = vr.mTemp;
|
|
ins.mSType[1] = InterTypeOf(vl.mType);;
|
|
ins.mSTemp[1] = vl.mTemp;
|
|
ins.mTType = InterTypeOfArithmetic(ins.mSType[0], ins.mSType[1]);
|
|
ins.mTTemp = proc->AddTemporary(ins.mTType);
|
|
block->Append(ins);
|
|
}
|
|
|
|
return ExValue(vl.mType, ins.mTTemp);
|
|
}
|
|
|
|
|
|
case EX_PREINCDEC:
|
|
{
|
|
vl = TranslateExpression(procType, proc, block, exp->mLeft, breakBlock, continueBlock);
|
|
vl = Dereference(proc, block, vl, 1);
|
|
|
|
if (vl.mReference != 1)
|
|
mErrors->Error(exp->mLeft->mLocation, "Not a left hand expression");
|
|
|
|
if (vl.mType->mFlags & DTF_CONST)
|
|
mErrors->Error(exp->mLocation, "Cannot change const value");
|
|
|
|
InterInstruction cins, ains, rins, sins;
|
|
|
|
ExValue vdl = Dereference(proc, block, vl);
|
|
|
|
bool ftype = vl.mType->mType == DT_TYPE_FLOAT;
|
|
|
|
cins.mCode = IC_CONSTANT;
|
|
cins.mTType = ftype ? IT_FLOAT : IT_SIGNED;
|
|
cins.mTTemp = proc->AddTemporary(cins.mTType);
|
|
if (vdl.mType->mType == DT_TYPE_POINTER)
|
|
cins.mIntValue = exp->mToken == TK_INC ? vdl.mType->mBase->mSize : -(vdl.mType->mBase->mSize);
|
|
else if (vdl.mType->IsNumericType())
|
|
cins.mIntValue = exp->mToken == TK_INC ? 1 : -1;
|
|
else
|
|
mErrors->Error(exp->mLocation, "Not a numeric value or pointer");
|
|
|
|
block->Append(cins);
|
|
|
|
ains.mCode = IC_BINARY_OPERATOR;
|
|
ains.mOperator = IA_ADD;
|
|
ains.mSType[0] = cins.mTType;
|
|
ains.mSTemp[0] = cins.mTTemp;
|
|
ains.mSType[1] = InterTypeOf(vdl.mType);
|
|
ains.mSTemp[1] = vdl.mTemp;
|
|
ains.mTType = ains.mSType[1];
|
|
ains.mTTemp = proc->AddTemporary(ains.mTType);
|
|
block->Append(ains);
|
|
|
|
sins.mCode = IC_STORE;
|
|
sins.mMemory = IM_INDIRECT;
|
|
sins.mSType[0] = ains.mTType;
|
|
sins.mSTemp[0] = ains.mTTemp;
|
|
sins.mSType[1] = IT_POINTER;
|
|
sins.mSTemp[1] = vl.mTemp;
|
|
sins.mOperandSize = vl.mType->mSize;
|
|
block->Append(sins);
|
|
|
|
return ExValue(vdl.mType, ains.mTTemp);
|
|
}
|
|
break;
|
|
|
|
case EX_POSTINCDEC:
|
|
{
|
|
vl = TranslateExpression(procType, proc, block, exp->mLeft, breakBlock, continueBlock);
|
|
vl = Dereference(proc, block, vl, 1);
|
|
|
|
if (vl.mReference != 1)
|
|
mErrors->Error(exp->mLeft->mLocation, "Not a left hand expression");
|
|
|
|
if (vl.mType->mFlags & DTF_CONST)
|
|
mErrors->Error(exp->mLocation, "Cannot change const value");
|
|
|
|
InterInstruction cins, ains, rins, sins;
|
|
|
|
ExValue vdl = Dereference(proc, block, vl);
|
|
|
|
bool ftype = vl.mType->mType == DT_TYPE_FLOAT;
|
|
|
|
cins.mCode = IC_CONSTANT;
|
|
cins.mTType = ftype ? IT_FLOAT : IT_SIGNED;
|
|
cins.mTTemp = proc->AddTemporary(cins.mTType);
|
|
if (vdl.mType->mType == DT_TYPE_POINTER)
|
|
cins.mIntValue = exp->mToken == TK_INC ? vdl.mType->mBase->mSize : -(vdl.mType->mBase->mSize);
|
|
else if (vdl.mType->IsNumericType())
|
|
cins.mIntValue = exp->mToken == TK_INC ? 1 : -1;
|
|
else
|
|
mErrors->Error(exp->mLocation, "Not a numeric value or pointer");
|
|
block->Append(cins);
|
|
|
|
ains.mCode = IC_BINARY_OPERATOR;
|
|
ains.mOperator = IA_ADD;
|
|
ains.mSType[0] = cins.mTType;
|
|
ains.mSTemp[0] = cins.mTTemp;
|
|
ains.mSType[1] = InterTypeOf(vdl.mType);
|
|
ains.mSTemp[1] = vdl.mTemp;
|
|
ains.mTType = ains.mSType[1];
|
|
ains.mTTemp = proc->AddTemporary(ains.mTType);
|
|
block->Append(ains);
|
|
|
|
sins.mCode = IC_STORE;
|
|
sins.mMemory = IM_INDIRECT;
|
|
sins.mSType[0] = ains.mTType;
|
|
sins.mSTemp[0] = ains.mTTemp;
|
|
sins.mSType[1] = IT_POINTER;
|
|
sins.mSTemp[1] = vl.mTemp;
|
|
sins.mOperandSize = vl.mType->mSize;
|
|
block->Append(sins);
|
|
|
|
return ExValue(vdl.mType, vdl.mTemp);
|
|
}
|
|
break;
|
|
|
|
case EX_PREFIX:
|
|
{
|
|
vl = TranslateExpression(procType, proc, block, exp->mLeft, breakBlock, continueBlock);
|
|
|
|
InterInstruction ins;
|
|
|
|
ins.mCode = IC_UNARY_OPERATOR;
|
|
|
|
switch (exp->mToken)
|
|
{
|
|
case TK_ADD:
|
|
vl = Dereference(proc, block, vl);
|
|
ins.mOperator = IA_NONE;
|
|
break;
|
|
case TK_SUB:
|
|
vl = Dereference(proc, block, vl);
|
|
if (!vl.mType->IsNumericType())
|
|
mErrors->Error(exp->mLocation, "Not a numeric type");
|
|
ins.mOperator = IA_NEG;
|
|
break;
|
|
case TK_BINARY_NOT:
|
|
vl = Dereference(proc, block, vl);
|
|
if (!(vl.mType->mType == DT_TYPE_POINTER || vl.mType->IsNumericType()))
|
|
mErrors->Error(exp->mLocation, "Not a numeric or pointer type");
|
|
ins.mOperator = IA_NOT;
|
|
break;
|
|
case TK_MUL:
|
|
if (vl.mType->mType != DT_TYPE_POINTER)
|
|
mErrors->Error(exp->mLocation, "Not a pointer type");
|
|
return ExValue(vl.mType->mBase, vl.mTemp, vl.mReference + 1);
|
|
case TK_BINARY_AND:
|
|
{
|
|
if (vl.mReference < 1)
|
|
mErrors->Error(exp->mLocation, "Not an addressable value");
|
|
|
|
Declaration* dec = new Declaration(exp->mLocation, DT_TYPE_POINTER);
|
|
dec->mBase = vl.mType;
|
|
dec->mSize = 2;
|
|
dec->mFlags = DTF_DEFINED;
|
|
return ExValue(dec, vl.mTemp, vl.mReference - 1);
|
|
}
|
|
}
|
|
|
|
ins.mSType[0] = InterTypeOf(vl.mType);
|
|
ins.mSTemp[0] = vl.mTemp;
|
|
ins.mTType = ins.mSType[0];
|
|
ins.mTTemp = proc->AddTemporary(ins.mTType);
|
|
|
|
block->Append(ins);
|
|
|
|
return ExValue(vl.mType, ins.mTTemp);
|
|
}
|
|
|
|
case EX_RELATIONAL:
|
|
{
|
|
vl = TranslateExpression(procType, proc, block, exp->mLeft, breakBlock, continueBlock);
|
|
vl = Dereference(proc, block, vl);
|
|
vr = TranslateExpression(procType, proc, block, exp->mRight, breakBlock, continueBlock);
|
|
vr = Dereference(proc, block, vr);
|
|
|
|
InterInstruction ins;
|
|
|
|
bool signedCompare = (vl.mType->mFlags & DTF_SIGNED) && (vr.mType->mFlags & DTF_SIGNED);
|
|
|
|
if (!(vl.mType->mType == DT_TYPE_POINTER || vl.mType->IsNumericType()))
|
|
mErrors->Error(exp->mLocation, "Not a numeric or pointer type");
|
|
|
|
if (vl.mType->IsIntegerType() && vr.mType->mType == DT_TYPE_FLOAT)
|
|
{
|
|
InterInstruction cins;
|
|
cins.mCode = IC_CONVERSION_OPERATOR;
|
|
cins.mOperator = IA_INT2FLOAT;
|
|
cins.mSType[0] = InterTypeOf(vl.mType);
|
|
cins.mSTemp[0] = vl.mTemp;
|
|
cins.mTType = IT_FLOAT;
|
|
cins.mTTemp = proc->AddTemporary(cins.mTType);
|
|
vl.mTemp = cins.mTTemp;
|
|
vl.mType = TheFloatTypeDeclaration;
|
|
block->Append(cins);
|
|
}
|
|
else if (vl.mType->mType == DT_TYPE_FLOAT && vr.mType->IsIntegerType())
|
|
{
|
|
InterInstruction cins;
|
|
cins.mCode = IC_CONVERSION_OPERATOR;
|
|
cins.mOperator = IA_INT2FLOAT;
|
|
cins.mSType[0] = InterTypeOf(vr.mType);
|
|
cins.mSTemp[0] = vr.mTemp;
|
|
cins.mTType = IT_FLOAT;
|
|
cins.mTTemp = proc->AddTemporary(cins.mTType);
|
|
vr.mTemp = cins.mTTemp;
|
|
vr.mType = TheFloatTypeDeclaration;
|
|
block->Append(cins);
|
|
}
|
|
|
|
ins.mCode = IC_RELATIONAL_OPERATOR;
|
|
switch (exp->mToken)
|
|
{
|
|
case TK_EQUAL:
|
|
ins.mOperator = IA_CMPEQ;
|
|
break;
|
|
case TK_NOT_EQUAL:
|
|
ins.mOperator = IA_CMPNE;
|
|
break;
|
|
case TK_GREATER_THAN:
|
|
ins.mOperator = signedCompare ? IA_CMPGS : IA_CMPGU;
|
|
break;
|
|
case TK_GREATER_EQUAL:
|
|
ins.mOperator = signedCompare ? IA_CMPGES : IA_CMPGEU;
|
|
break;
|
|
case TK_LESS_THAN:
|
|
ins.mOperator = signedCompare ? IA_CMPLS : IA_CMPLU;
|
|
break;
|
|
case TK_LESS_EQUAL:
|
|
ins.mOperator = signedCompare ? IA_CMPLES : IA_CMPLEU;
|
|
break;
|
|
}
|
|
ins.mSType[0] = InterTypeOf(vr.mType);;
|
|
ins.mSTemp[0] = vr.mTemp;
|
|
ins.mSType[1] = InterTypeOf(vl.mType);;
|
|
ins.mSTemp[1] = vl.mTemp;
|
|
ins.mTType = IT_BOOL;
|
|
ins.mTTemp = proc->AddTemporary(ins.mTType);
|
|
|
|
block->Append(ins);
|
|
|
|
return ExValue(TheBoolTypeDeclaration, ins.mTTemp);
|
|
}
|
|
|
|
case EX_CALL:
|
|
{
|
|
if (exp->mLeft->mType == EX_CONSTANT && exp->mLeft->mDecValue->mType == DT_CONST_FUNCTION && (exp->mLeft->mDecValue->mFlags & DTF_INTRINSIC))
|
|
{
|
|
Declaration* decf = exp->mLeft->mDecValue;
|
|
const Ident * iname = decf->mIdent;
|
|
|
|
if (!strcmp(iname->mString, "fabs"))
|
|
{
|
|
vr = TranslateExpression(procType, proc, block, exp->mRight, breakBlock, continueBlock);
|
|
vr = Dereference(proc, block, vr);
|
|
|
|
if (decf->mBase->mParams->CanAssign(vr.mType))
|
|
mErrors->Error(exp->mLocation, "Cannot assign incompatible types");
|
|
vr = CoerceType(proc, block, vr, decf->mBase->mParams);
|
|
|
|
InterInstruction ins;
|
|
ins.mCode = IC_UNARY_OPERATOR;
|
|
ins.mOperator = IA_ABS;
|
|
ins.mSType[0] = IT_FLOAT;
|
|
ins.mSTemp[0] = vr.mTemp;
|
|
ins.mTType = IT_FLOAT;
|
|
ins.mTTemp = proc->AddTemporary(ins.mTType);
|
|
block->Append(ins);
|
|
|
|
return ExValue(TheFloatTypeDeclaration, ins.mTTemp);
|
|
}
|
|
else if (!strcmp(iname->mString, "floor"))
|
|
{
|
|
vr = TranslateExpression(procType, proc, block, exp->mRight, breakBlock, continueBlock);
|
|
vr = Dereference(proc, block, vr);
|
|
|
|
if (decf->mBase->mParams->CanAssign(vr.mType))
|
|
mErrors->Error(exp->mLocation, "Cannot assign incompatible types");
|
|
vr = CoerceType(proc, block, vr, decf->mBase->mParams);
|
|
|
|
InterInstruction ins;
|
|
ins.mCode = IC_UNARY_OPERATOR;
|
|
ins.mOperator = IA_FLOOR;
|
|
ins.mSType[0] = IT_FLOAT;
|
|
ins.mSTemp[0] = vr.mTemp;
|
|
ins.mTType = IT_FLOAT;
|
|
ins.mTTemp = proc->AddTemporary(ins.mTType);
|
|
block->Append(ins);
|
|
|
|
return ExValue(TheFloatTypeDeclaration, ins.mTTemp);
|
|
}
|
|
else if (!strcmp(iname->mString, "ceil"))
|
|
{
|
|
vr = TranslateExpression(procType, proc, block, exp->mRight, breakBlock, continueBlock);
|
|
vr = Dereference(proc, block, vr);
|
|
|
|
if (decf->mBase->mParams->CanAssign(vr.mType))
|
|
mErrors->Error(exp->mLocation, "Cannot assign incompatible types");
|
|
vr = CoerceType(proc, block, vr, decf->mBase->mParams);
|
|
|
|
InterInstruction ins;
|
|
ins.mCode = IC_UNARY_OPERATOR;
|
|
ins.mOperator = IA_CEIL;
|
|
ins.mSType[0] = IT_FLOAT;
|
|
ins.mSTemp[0] = vr.mTemp;
|
|
ins.mTType = IT_FLOAT;
|
|
ins.mTTemp = proc->AddTemporary(ins.mTType);
|
|
block->Append(ins);
|
|
|
|
return ExValue(TheFloatTypeDeclaration, ins.mTTemp);
|
|
}
|
|
else
|
|
mErrors->Error(exp->mLeft->mDecValue->mLocation, "Unknown intrinsic function", iname->mString);
|
|
|
|
return ExValue(TheVoidTypeDeclaration);
|
|
}
|
|
else
|
|
{
|
|
vl = TranslateExpression(procType, proc, block, exp->mLeft, breakBlock, continueBlock);
|
|
vl = Dereference(proc, block, vl);
|
|
|
|
int atotal = 0;
|
|
|
|
int findex = block->mInstructions.Size();
|
|
InterCodeBasicBlock* fblock = block;
|
|
|
|
InterInstruction fins;
|
|
fins.mCode = IC_PUSH_FRAME;
|
|
fins.mIntValue = atotal;
|
|
block->Append(fins);
|
|
|
|
Declaration * ftype = vl.mType;
|
|
if (ftype->mType == DT_TYPE_POINTER)
|
|
ftype = ftype->mBase;
|
|
|
|
Declaration* pdec = ftype->mParams;
|
|
Expression* pex = exp->mRight;
|
|
while (pex)
|
|
{
|
|
InterInstruction ains;
|
|
ains.mCode = IC_CONSTANT;
|
|
ains.mTType = IT_POINTER;
|
|
ains.mTTemp = proc->AddTemporary(ains.mTType);
|
|
ains.mMemory = IM_FRAME;
|
|
if (pdec)
|
|
{
|
|
ains.mVarIndex = pdec->mVarIndex;
|
|
ains.mIntValue = pdec->mOffset;
|
|
ains.mOperandSize = pdec->mSize;
|
|
}
|
|
else if (ftype->mFlags & DTF_VARIADIC)
|
|
{
|
|
ains.mVarIndex = atotal;
|
|
ains.mIntValue = 0;
|
|
ains.mOperandSize = 2;
|
|
}
|
|
else
|
|
{
|
|
mErrors->Error(pex->mLocation, "Too many arguments for function call");
|
|
}
|
|
block->Append(ains);
|
|
|
|
Expression* texp;
|
|
|
|
if (pex->mType == EX_LIST)
|
|
{
|
|
texp = pex->mLeft;
|
|
pex = pex->mRight;
|
|
}
|
|
else
|
|
{
|
|
texp = pex;
|
|
pex = nullptr;
|
|
}
|
|
|
|
vr = TranslateExpression(procType, proc, block, texp, breakBlock, continueBlock);
|
|
|
|
if (vr.mType->mType != DT_TYPE_ARRAY)
|
|
vr = Dereference(proc, block, vr);
|
|
|
|
if (pdec)
|
|
{
|
|
if (!pdec->mBase->CanAssign(vr.mType))
|
|
mErrors->Error(texp->mLocation, "Cannot assign incompatible types");
|
|
vr = CoerceType(proc, block, vr, pdec->mBase);
|
|
}
|
|
|
|
InterInstruction wins;
|
|
wins.mCode = IC_STORE;
|
|
wins.mMemory = IM_INDIRECT;
|
|
wins.mSType[0] = InterTypeOf(vr.mType);;
|
|
wins.mSTemp[0] = vr.mTemp;
|
|
wins.mSType[1] = IT_POINTER;
|
|
wins.mSTemp[1] = ains.mTTemp;
|
|
if (pdec)
|
|
wins.mOperandSize = pdec->mSize;
|
|
else if (vr.mType->mSize > 2 && vr.mType->mType != DT_TYPE_ARRAY)
|
|
wins.mOperandSize = vr.mType->mSize;
|
|
else
|
|
wins.mOperandSize = 2;
|
|
|
|
block->Append(wins);
|
|
|
|
atotal += wins.mOperandSize;
|
|
if (pdec)
|
|
pdec = pdec->mNext;
|
|
}
|
|
|
|
if (pdec)
|
|
mErrors->Error(exp->mLocation, "Not enough arguments for function call");
|
|
|
|
InterInstruction cins;
|
|
if (exp->mLeft->mDecValue && exp->mLeft->mDecValue->mFlags & DTF_NATIVE)
|
|
cins.mCode = IC_JSR;
|
|
else
|
|
cins.mCode = IC_CALL;
|
|
cins.mSType[0] = IT_POINTER;
|
|
cins.mSTemp[0] = vl.mTemp;
|
|
if (ftype->mBase->mType != DT_TYPE_VOID)
|
|
{
|
|
cins.mTType = InterTypeOf(ftype->mBase);
|
|
cins.mTTemp = proc->AddTemporary(cins.mTType);
|
|
}
|
|
|
|
block->Append(cins);
|
|
|
|
fblock->mInstructions[findex].mIntValue = atotal;
|
|
|
|
InterInstruction xins;
|
|
xins.mCode = IC_POP_FRAME;
|
|
xins.mIntValue = atotal;
|
|
block->Append(xins);
|
|
|
|
return ExValue(ftype->mBase, cins.mTTemp);
|
|
}
|
|
|
|
}
|
|
|
|
case EX_ASSEMBLER:
|
|
{
|
|
int offset = 0, osize = 0;
|
|
Expression* cexp = exp;
|
|
while (cexp)
|
|
{
|
|
osize += AsmInsSize(cexp->mAsmInsType, cexp->mAsmInsMode);
|
|
cexp = cexp->mRight;
|
|
}
|
|
|
|
InterInstruction ins;
|
|
ins.mCode = IC_CONSTANT;
|
|
ins.mTType = IT_POINTER;
|
|
ins.mTTemp = proc->AddTemporary(ins.mTType);
|
|
ins.mOperandSize = osize;
|
|
ins.mIntValue = 0;
|
|
|
|
InterVariable var;
|
|
var.mOffset = 0;
|
|
var.mSize = osize;
|
|
uint8* d = new uint8[osize];
|
|
var.mData = d;
|
|
var.mAssembler = true;
|
|
|
|
|
|
var.mIndex = proc->mModule->mGlobalVars.Size();
|
|
if (exp->mDecValue)
|
|
{
|
|
exp->mDecValue->mVarIndex = var.mIndex;
|
|
var.mIdent = exp->mDecValue->mIdent;
|
|
}
|
|
proc->mModule->mGlobalVars.Push(var);
|
|
|
|
GrowingArray<InterVariable::Reference> references({ 0 });
|
|
|
|
cexp = exp;
|
|
while (cexp)
|
|
{
|
|
if (cexp->mAsmInsType != ASMIT_BYTE)
|
|
{
|
|
int opcode = AsmInsOpcodes[cexp->mAsmInsType][cexp->mAsmInsMode];
|
|
d[offset++] = opcode;
|
|
}
|
|
|
|
Declaration* aexp = nullptr;
|
|
if (cexp->mLeft)
|
|
aexp = cexp->mLeft->mDecValue;
|
|
|
|
switch (cexp->mAsmInsMode)
|
|
{
|
|
case ASMIM_IMPLIED:
|
|
break;
|
|
case ASMIM_IMMEDIATE:
|
|
case ASMIM_ZERO_PAGE:
|
|
case ASMIM_ZERO_PAGE_X:
|
|
case ASMIM_INDIRECT_X:
|
|
case ASMIM_INDIRECT_Y:
|
|
d[offset++] = aexp->mInteger;
|
|
break;
|
|
case ASMIM_ABSOLUTE:
|
|
case ASMIM_INDIRECT:
|
|
case ASMIM_ABSOLUTE_X:
|
|
case ASMIM_ABSOLUTE_Y:
|
|
if (aexp->mType == DT_CONST_INTEGER)
|
|
{
|
|
d[offset++] = cexp->mLeft->mDecValue->mInteger & 255;
|
|
d[offset++] = cexp->mLeft->mDecValue->mInteger >> 8;
|
|
}
|
|
else if (aexp->mType == DT_LABEL)
|
|
{
|
|
if (aexp->mBase->mVarIndex < 0)
|
|
{
|
|
InterCodeBasicBlock* bblock = nullptr;
|
|
TranslateExpression(procType, proc, bblock, aexp->mBase->mValue, breakBlock, continueBlock);
|
|
}
|
|
|
|
InterVariable::Reference ref;
|
|
ref.mFunction = false;
|
|
ref.mUpper = true;
|
|
ref.mLower = true;
|
|
ref.mAddr = offset;
|
|
ref.mIndex = aexp->mBase->mVarIndex;
|
|
ref.mOffset = aexp->mInteger;
|
|
|
|
references.Push(ref);
|
|
|
|
offset += 2;
|
|
}
|
|
else if (aexp->mType == DT_LABEL_REF)
|
|
{
|
|
if (aexp->mBase->mBase->mVarIndex < 0)
|
|
{
|
|
InterCodeBasicBlock* bblock = nullptr;
|
|
TranslateExpression(procType, proc, bblock, aexp->mBase->mBase->mValue, breakBlock, continueBlock);
|
|
}
|
|
|
|
InterVariable::Reference ref;
|
|
ref.mFunction = false;
|
|
ref.mUpper = true;
|
|
ref.mLower = true;
|
|
ref.mAddr = offset;
|
|
ref.mIndex = aexp->mBase->mBase->mVarIndex;
|
|
ref.mOffset = aexp->mOffset + aexp->mBase->mInteger;
|
|
|
|
references.Push(ref);
|
|
|
|
offset += 2;
|
|
}
|
|
else if (aexp->mType == DT_CONST_ASSEMBLER)
|
|
{
|
|
if (aexp->mVarIndex < 0)
|
|
{
|
|
InterCodeBasicBlock* bblock = nullptr;
|
|
TranslateExpression(procType, proc, bblock, aexp->mValue, breakBlock, continueBlock);
|
|
}
|
|
|
|
InterVariable::Reference ref;
|
|
ref.mFunction = false;
|
|
ref.mUpper = true;
|
|
ref.mLower = true;
|
|
ref.mAddr = offset;
|
|
ref.mIndex = aexp->mVarIndex;
|
|
ref.mOffset = 0;
|
|
|
|
references.Push(ref);
|
|
|
|
offset += 2;
|
|
}
|
|
else if (aexp->mType == DT_VARIABLE)
|
|
{
|
|
if (aexp->mFlags & DTF_GLOBAL)
|
|
{
|
|
InitGlobalVariable(proc->mModule, aexp);
|
|
|
|
InterVariable::Reference ref;
|
|
ref.mFunction = false;
|
|
ref.mUpper = true;
|
|
ref.mLower = true;
|
|
ref.mAddr = offset;
|
|
ref.mIndex = aexp->mVarIndex;
|
|
ref.mOffset = 0;
|
|
|
|
references.Push(ref);
|
|
|
|
offset += 2;
|
|
}
|
|
}
|
|
break;
|
|
case ASMIM_RELATIVE:
|
|
d[offset] = aexp->mInteger - offset - 1;
|
|
offset++;
|
|
break;
|
|
}
|
|
|
|
cexp = cexp->mRight;
|
|
}
|
|
|
|
assert(offset == osize);
|
|
|
|
InterVariable& ivar(proc->mModule->mGlobalVars[var.mIndex]);
|
|
|
|
ivar.mNumReferences = references.Size();
|
|
if (ivar.mNumReferences)
|
|
{
|
|
ivar.mReferences = new InterVariable::Reference[ivar.mNumReferences];
|
|
for (int i = 0; i < ivar.mNumReferences; i++)
|
|
ivar.mReferences[i] = references[i];
|
|
}
|
|
|
|
if (block)
|
|
{
|
|
ins.mMemory = IM_GLOBAL;
|
|
ins.mVarIndex = var.mIndex;
|
|
block->Append(ins);
|
|
|
|
InterInstruction jins;
|
|
jins.mCode = IC_JSR;
|
|
jins.mSType[0] = IT_POINTER;
|
|
jins.mSTemp[0] = ins.mTTemp;
|
|
|
|
block->Append(jins);
|
|
}
|
|
|
|
return ExValue(TheVoidTypeDeclaration);
|
|
}
|
|
|
|
case EX_RETURN:
|
|
{
|
|
InterInstruction ins;
|
|
if (exp->mLeft)
|
|
{
|
|
vr = TranslateExpression(procType, proc, block, exp->mLeft, breakBlock, continueBlock);
|
|
vr = Dereference(proc, block, vr);
|
|
|
|
if (!procType->mBase || procType->mBase->mType == DT_TYPE_VOID)
|
|
mErrors->Error(exp->mLocation, "Function has void return type");
|
|
else if (!procType->mBase->CanAssign(vr.mType))
|
|
mErrors->Error(exp->mLocation, "Cannot return incompatible type");
|
|
|
|
ins.mSType[0] = InterTypeOf(vr.mType);
|
|
ins.mSTemp[0] = vr.mTemp;
|
|
ins.mCode = IC_RETURN_VALUE;
|
|
}
|
|
else
|
|
{
|
|
if (procType->mBase && procType->mBase->mType != DT_TYPE_VOID)
|
|
mErrors->Error(exp->mLocation, "Function has non void return type");
|
|
|
|
ins.mCode = IC_RETURN;
|
|
}
|
|
|
|
block->Append(ins);
|
|
block->Close(nullptr, nullptr);
|
|
block = new InterCodeBasicBlock();
|
|
proc->Append(block);
|
|
|
|
return ExValue(TheVoidTypeDeclaration);
|
|
}
|
|
|
|
case EX_BREAK:
|
|
{
|
|
if (breakBlock)
|
|
{
|
|
InterInstruction jins;
|
|
jins.mCode = IC_JUMP;
|
|
block->Append(jins);
|
|
|
|
block->Close(breakBlock, nullptr);
|
|
block = new InterCodeBasicBlock();
|
|
proc->Append(block);
|
|
}
|
|
else
|
|
mErrors->Error(exp->mLocation, "No break target");
|
|
|
|
return ExValue(TheVoidTypeDeclaration);
|
|
}
|
|
|
|
case EX_CONTINUE:
|
|
{
|
|
if (continueBlock)
|
|
{
|
|
InterInstruction jins;
|
|
jins.mCode = IC_JUMP;
|
|
block->Append(jins);
|
|
|
|
block->Close(continueBlock, nullptr);
|
|
block = new InterCodeBasicBlock();
|
|
proc->Append(block);
|
|
}
|
|
else
|
|
mErrors->Error(exp->mLocation, "No continue target");
|
|
|
|
return ExValue(TheVoidTypeDeclaration);
|
|
}
|
|
|
|
case EX_LOGICAL_NOT:
|
|
{
|
|
vl = TranslateExpression(procType, proc, block, exp->mLeft, breakBlock, continueBlock);
|
|
vl = Dereference(proc, block, vl);
|
|
|
|
InterInstruction zins;
|
|
zins.mCode = IC_CONSTANT;
|
|
zins.mTType = InterTypeOf(vr.mType);
|
|
zins.mTTemp = proc->AddTemporary(zins.mTType);
|
|
zins.mIntValue = 0;
|
|
block->Append(zins);
|
|
|
|
InterInstruction ins;
|
|
ins.mCode = IC_RELATIONAL_OPERATOR;
|
|
ins.mOperator = IA_CMPNE;
|
|
ins.mSType[0] = InterTypeOf(vr.mType);
|
|
ins.mSTemp[0] = zins.mTTemp;
|
|
ins.mSType[1] = InterTypeOf(vr.mType);
|
|
ins.mSTemp[1] = vl.mTemp;
|
|
ins.mTType = IT_BOOL;
|
|
ins.mTTemp = proc->AddTemporary(ins.mTType);
|
|
block->Append(ins);
|
|
|
|
return ExValue(TheBoolTypeDeclaration, ins.mTTemp);
|
|
}
|
|
|
|
case EX_CONDITIONAL:
|
|
{
|
|
InterInstruction jins;
|
|
jins.mCode = IC_JUMP;
|
|
|
|
InterCodeBasicBlock* tblock = new InterCodeBasicBlock();
|
|
proc->Append(tblock);
|
|
InterCodeBasicBlock* fblock = new InterCodeBasicBlock();
|
|
proc->Append(fblock);
|
|
InterCodeBasicBlock* eblock = new InterCodeBasicBlock();
|
|
proc->Append(eblock);
|
|
|
|
TranslateLogic(procType, proc, block, tblock, fblock, exp->mLeft);
|
|
|
|
vl = TranslateExpression(procType, proc, tblock, exp->mRight->mLeft, breakBlock, continueBlock);
|
|
vl = Dereference(proc, tblock, vl);
|
|
|
|
vr = TranslateExpression(procType, proc, fblock, exp->mRight->mRight, breakBlock, continueBlock);
|
|
vr = Dereference(proc, fblock, vr);
|
|
|
|
int ttemp;
|
|
InterType ttype;
|
|
Declaration* dtype;
|
|
if (vl.mType->mType == DT_TYPE_FLOAT || vr.mType->mType == DT_TYPE_FLOAT)
|
|
{
|
|
ttype = IT_FLOAT;
|
|
dtype = TheFloatTypeDeclaration;
|
|
}
|
|
else if (vl.mType->IsIntegerType() && vr.mType->IsIntegerType())
|
|
{
|
|
ttype = ((vl.mType->mFlags & DTF_SIGNED) && (vr.mType->mFlags & DTF_SIGNED)) ? IT_SIGNED : IT_UNSIGNED;
|
|
dtype = vl.mType;
|
|
}
|
|
else if (vl.mType->mType == DT_TYPE_POINTER && vl.mType->IsSame(vr.mType))
|
|
{
|
|
ttype = IT_POINTER;
|
|
dtype = vl.mType;
|
|
}
|
|
else
|
|
{
|
|
mErrors->Error(exp->mLocation, "Incompatible conditional types");
|
|
ttype = IT_SIGNED;
|
|
dtype = TheVoidTypeDeclaration;
|
|
}
|
|
ttemp = proc->AddTemporary(ttype);
|
|
|
|
if (ttype == IT_FLOAT && vr.mType->IsIntegerType())
|
|
{
|
|
InterInstruction ins;
|
|
ins.mCode = IC_CONVERSION_OPERATOR;
|
|
ins.mOperator = IA_INT2FLOAT;
|
|
ins.mSType[0] = InterTypeOf(vr.mType);
|
|
ins.mSTemp[0] = vr.mTemp;
|
|
ins.mTType = ttype;
|
|
ins.mTTemp = ttemp;
|
|
fblock->Append(ins);
|
|
}
|
|
else
|
|
{
|
|
InterInstruction ins;
|
|
ins.mCode = IC_LOAD_TEMPORARY;
|
|
ins.mSType[0] = InterTypeOf(vr.mType);
|
|
ins.mSTemp[0] = vr.mTemp;
|
|
ins.mTType = ttype;
|
|
ins.mTTemp = ttemp;
|
|
fblock->Append(ins);
|
|
}
|
|
|
|
if (ttype == IT_FLOAT && vl.mType->IsIntegerType())
|
|
{
|
|
InterInstruction ins;
|
|
ins.mCode = IC_CONVERSION_OPERATOR;
|
|
ins.mOperator = IA_INT2FLOAT;
|
|
ins.mSType[0] = InterTypeOf(vl.mType);
|
|
ins.mSTemp[0] = vl.mTemp;
|
|
ins.mTType = ttype;
|
|
ins.mTTemp = ttemp;
|
|
tblock->Append(ins);
|
|
}
|
|
else
|
|
{
|
|
InterInstruction ins;
|
|
ins.mCode = IC_LOAD_TEMPORARY;
|
|
ins.mSType[0] = InterTypeOf(vl.mType);
|
|
ins.mSTemp[0] = vl.mTemp;
|
|
ins.mTType = ttype;
|
|
ins.mTTemp = ttemp;
|
|
tblock->Append(ins);
|
|
}
|
|
|
|
tblock->Append(jins);
|
|
tblock->Close(eblock, nullptr);
|
|
|
|
fblock->Append(jins);
|
|
fblock->Close(eblock, nullptr);
|
|
|
|
block = eblock;
|
|
|
|
return ExValue(dtype, ttemp);
|
|
|
|
break;
|
|
}
|
|
|
|
case EX_TYPECAST:
|
|
{
|
|
vr = TranslateExpression(procType, proc, block, exp->mRight, breakBlock, continueBlock);
|
|
|
|
InterInstruction ins;
|
|
|
|
if (exp->mLeft->mDecType->mType == DT_TYPE_FLOAT && vr.mType->IsIntegerType())
|
|
{
|
|
vr = Dereference(proc, block, vr);
|
|
ins.mCode = IC_CONVERSION_OPERATOR;
|
|
ins.mOperator = IA_INT2FLOAT;
|
|
ins.mSType[0] = InterTypeOf(vr.mType);
|
|
ins.mSTemp[0] = vr.mTemp;
|
|
ins.mTType = InterTypeOf(exp->mLeft->mDecType);
|
|
ins.mTTemp = proc->AddTemporary(ins.mTType);
|
|
block->Append(ins);
|
|
}
|
|
else if (exp->mLeft->mDecType->IsIntegerType() && vr.mType->mType == DT_TYPE_FLOAT)
|
|
{
|
|
vr = Dereference(proc, block, vr);
|
|
ins.mCode = IC_CONVERSION_OPERATOR;
|
|
ins.mOperator = IA_FLOAT2INT;
|
|
ins.mSType[0] = InterTypeOf(vr.mType);
|
|
ins.mSTemp[0] = vr.mTemp;
|
|
ins.mTType = InterTypeOf(exp->mLeft->mDecType);
|
|
ins.mTTemp = proc->AddTemporary(ins.mTType);
|
|
block->Append(ins);
|
|
}
|
|
else if (exp->mLeft->mDecType->mType == DT_TYPE_POINTER && vr.mType->mType == DT_TYPE_POINTER)
|
|
{
|
|
// no need for actual operation when casting pointer to pointer
|
|
return ExValue(exp->mLeft->mDecType, vr.mTemp, vr.mReference);
|
|
}
|
|
else
|
|
{
|
|
vr = Dereference(proc, block, vr);
|
|
ins.mCode = IC_TYPECAST;
|
|
ins.mSType[0] = InterTypeOf(vr.mType);
|
|
ins.mSTemp[0] = vr.mTemp;
|
|
ins.mTType = InterTypeOf(exp->mLeft->mDecType);
|
|
ins.mTTemp = proc->AddTemporary(ins.mTType);
|
|
block->Append(ins);
|
|
}
|
|
|
|
return ExValue(exp->mLeft->mDecType, ins.mTTemp);
|
|
}
|
|
break;
|
|
|
|
case EX_LOGICAL_AND:
|
|
{
|
|
|
|
}
|
|
case EX_WHILE:
|
|
{
|
|
InterInstruction jins;
|
|
jins.mCode = IC_JUMP;
|
|
|
|
InterCodeBasicBlock* cblock = new InterCodeBasicBlock();
|
|
InterCodeBasicBlock* lblock = cblock;
|
|
proc->Append(cblock);
|
|
InterCodeBasicBlock* bblock = new InterCodeBasicBlock();
|
|
proc->Append(bblock);
|
|
InterCodeBasicBlock* eblock = new InterCodeBasicBlock();
|
|
proc->Append(eblock);
|
|
|
|
block->Append(jins);
|
|
block->Close(cblock, nullptr);
|
|
|
|
TranslateLogic(procType, proc, cblock, bblock, eblock, exp->mLeft);
|
|
|
|
vr = TranslateExpression(procType, proc, bblock, exp->mRight, eblock, lblock);
|
|
bblock->Append(jins);
|
|
bblock->Close(lblock, nullptr);
|
|
|
|
block = eblock;
|
|
|
|
return ExValue(TheVoidTypeDeclaration);
|
|
}
|
|
|
|
case EX_IF:
|
|
{
|
|
InterInstruction jins;
|
|
jins.mCode = IC_JUMP;
|
|
|
|
InterCodeBasicBlock* tblock = new InterCodeBasicBlock();
|
|
proc->Append(tblock);
|
|
InterCodeBasicBlock* fblock = new InterCodeBasicBlock();
|
|
proc->Append(fblock);
|
|
InterCodeBasicBlock* eblock = new InterCodeBasicBlock();
|
|
proc->Append(eblock);
|
|
|
|
TranslateLogic(procType, proc, block, tblock, fblock, exp->mLeft);
|
|
|
|
vr = TranslateExpression(procType, proc, tblock, exp->mRight->mLeft, breakBlock, continueBlock);
|
|
tblock->Append(jins);
|
|
tblock->Close(eblock, nullptr);
|
|
|
|
if (exp->mRight->mRight)
|
|
vr = TranslateExpression(procType, proc, fblock, exp->mRight->mRight, breakBlock, continueBlock);
|
|
fblock->Append(jins);
|
|
fblock->Close(eblock, nullptr);
|
|
|
|
block = eblock;
|
|
|
|
return ExValue(TheVoidTypeDeclaration);
|
|
}
|
|
|
|
case EX_FOR:
|
|
{
|
|
// assignment
|
|
if (exp->mLeft->mRight)
|
|
TranslateExpression(procType, proc, block, exp->mLeft->mRight, breakBlock, continueBlock);
|
|
|
|
InterInstruction jins;
|
|
jins.mCode = IC_JUMP;
|
|
|
|
InterCodeBasicBlock* cblock = new InterCodeBasicBlock();
|
|
InterCodeBasicBlock* lblock = cblock;
|
|
proc->Append(cblock);
|
|
InterCodeBasicBlock* bblock = new InterCodeBasicBlock();
|
|
proc->Append(bblock);
|
|
InterCodeBasicBlock* iblock = new InterCodeBasicBlock();
|
|
proc->Append(iblock);
|
|
InterCodeBasicBlock* eblock = new InterCodeBasicBlock();
|
|
proc->Append(eblock);
|
|
|
|
block->Append(jins);
|
|
block->Close(cblock, nullptr);
|
|
|
|
// condition
|
|
if (exp->mLeft->mLeft->mLeft)
|
|
TranslateLogic(procType, proc, cblock, bblock, eblock, exp->mLeft->mLeft->mLeft);
|
|
else
|
|
{
|
|
cblock->Append(jins);
|
|
cblock->Close(bblock, nullptr);
|
|
}
|
|
|
|
vr = TranslateExpression(procType, proc, bblock, exp->mRight, eblock, iblock);
|
|
|
|
bblock->Append(jins);
|
|
bblock->Close(iblock, nullptr);
|
|
|
|
// increment
|
|
if (exp->mLeft->mLeft->mRight)
|
|
TranslateExpression(procType, proc, iblock, exp->mLeft->mLeft->mRight, breakBlock, continueBlock);
|
|
|
|
iblock->Append(jins);
|
|
iblock->Close(lblock, nullptr);
|
|
|
|
block = eblock;
|
|
|
|
return ExValue(TheVoidTypeDeclaration);
|
|
}
|
|
|
|
case EX_DO:
|
|
{
|
|
InterInstruction jins;
|
|
jins.mCode = IC_JUMP;
|
|
|
|
InterCodeBasicBlock* cblock = new InterCodeBasicBlock();
|
|
InterCodeBasicBlock* lblock = cblock;
|
|
proc->Append(cblock);
|
|
InterCodeBasicBlock* eblock = new InterCodeBasicBlock();
|
|
proc->Append(eblock);
|
|
|
|
block->Append(jins);
|
|
block->Close(cblock, nullptr);
|
|
|
|
vr = TranslateExpression(procType, proc, cblock, exp->mRight, eblock, cblock);
|
|
|
|
TranslateLogic(procType, proc, cblock, lblock, eblock, exp->mLeft);
|
|
|
|
block = eblock;
|
|
|
|
return ExValue(TheVoidTypeDeclaration);
|
|
}
|
|
|
|
case EX_SWITCH:
|
|
{
|
|
InterInstruction jins;
|
|
jins.mCode = IC_JUMP;
|
|
|
|
vl = TranslateExpression(procType, proc, block, exp->mLeft, breakBlock, continueBlock);
|
|
vl = Dereference(proc, block, vl);
|
|
|
|
InterCodeBasicBlock * dblock = nullptr;
|
|
InterCodeBasicBlock* sblock = block;
|
|
|
|
block = nullptr;
|
|
|
|
InterCodeBasicBlock* eblock = new InterCodeBasicBlock();
|
|
proc->Append(eblock);
|
|
|
|
Expression* sexp = exp->mRight;
|
|
while (sexp)
|
|
{
|
|
Expression* cexp = sexp->mLeft;
|
|
if (cexp->mType == EX_CASE)
|
|
{
|
|
InterCodeBasicBlock* cblock = new InterCodeBasicBlock();
|
|
proc->Append(cblock);
|
|
|
|
InterCodeBasicBlock* nblock = new InterCodeBasicBlock();
|
|
proc->Append(nblock);
|
|
|
|
vr = TranslateExpression(procType, proc, sblock, cexp->mLeft, breakBlock, continueBlock);
|
|
vr = Dereference(proc, sblock, vr);
|
|
|
|
InterInstruction cins;
|
|
cins.mCode = IC_RELATIONAL_OPERATOR;
|
|
cins.mOperator = IA_CMPEQ;
|
|
cins.mSType[0] = InterTypeOf(vr.mType);;
|
|
cins.mSTemp[0] = vr.mTemp;
|
|
cins.mSType[1] = InterTypeOf(vl.mType);;
|
|
cins.mSTemp[1] = vl.mTemp;
|
|
cins.mTType = IT_BOOL;
|
|
cins.mTTemp = proc->AddTemporary(cins.mTType);
|
|
|
|
sblock->Append(cins);
|
|
|
|
InterInstruction bins;
|
|
bins.mCode = IC_BRANCH;
|
|
bins.mSType[0] = IT_BOOL;
|
|
bins.mSTemp[0] = cins.mTTemp;
|
|
sblock->Append(bins);
|
|
|
|
sblock->Close(nblock, cblock);
|
|
|
|
if (block)
|
|
{
|
|
block->Append(jins);
|
|
block->Close(nblock, nullptr);
|
|
}
|
|
|
|
sblock = cblock;
|
|
block = nblock;
|
|
}
|
|
else if (cexp->mType == EX_DEFAULT)
|
|
{
|
|
if (!dblock)
|
|
{
|
|
dblock = new InterCodeBasicBlock();
|
|
proc->Append(dblock);
|
|
|
|
if (block)
|
|
{
|
|
block->Append(jins);
|
|
block->Close(dblock, nullptr);
|
|
}
|
|
|
|
block = dblock;
|
|
}
|
|
else
|
|
mErrors->Error(cexp->mLocation, "Duplicate default");
|
|
}
|
|
|
|
if (cexp->mRight)
|
|
TranslateExpression(procType, proc, block, cexp->mRight, eblock, continueBlock);
|
|
|
|
sexp = sexp->mRight;
|
|
}
|
|
|
|
sblock->Append(jins);
|
|
if (dblock)
|
|
sblock->Close(dblock, nullptr);
|
|
else
|
|
sblock->Close(eblock, nullptr);
|
|
|
|
if (block)
|
|
{
|
|
block->Append(jins);
|
|
block->Close(eblock, nullptr);
|
|
}
|
|
|
|
block = eblock;
|
|
|
|
return ExValue(TheVoidTypeDeclaration);
|
|
}
|
|
default:
|
|
mErrors->Error(exp->mLocation, "Unimplemented expression");
|
|
return ExValue(TheVoidTypeDeclaration);
|
|
}
|
|
}
|
|
}
|
|
|
|
void InterCodeGenerator::BuildInitializer(InterCodeModule * mod, uint8* dp, int offset, Declaration* data, GrowingArray<InterVariable::Reference>& references)
|
|
{
|
|
if (data->mType == DT_CONST_DATA)
|
|
{
|
|
memcpy(dp + offset, data->mData, data->mBase->mSize);
|
|
}
|
|
else if (data->mType == DT_CONST_STRUCT)
|
|
{
|
|
Declaration* mdec = data->mParams;
|
|
while (mdec)
|
|
{
|
|
BuildInitializer(mod, dp, offset + mdec->mOffset, mdec, references);
|
|
mdec = mdec->mNext;
|
|
}
|
|
}
|
|
else if (data->mType == DT_CONST_INTEGER)
|
|
{
|
|
__int64 t = data->mInteger;
|
|
for (int i = 0; i < data->mBase->mSize; i++)
|
|
{
|
|
dp[offset + i] = uint8(t & 0xff);
|
|
t >>= 8;
|
|
}
|
|
}
|
|
else if (data->mType == DT_CONST_ADDRESS)
|
|
{
|
|
__int64 t = data->mInteger;
|
|
dp[offset + 0] = uint8(t & 0xff);
|
|
dp[offset + 1] = t >> 8;
|
|
}
|
|
else if (data->mType == DT_CONST_FLOAT)
|
|
{
|
|
union { float f; uint32 i; } cast;
|
|
cast.f = data->mNumber;
|
|
__int64 t = cast.i;
|
|
for (int i = 0; i < 4; i++)
|
|
{
|
|
dp[offset + i] = t & 0xff;
|
|
t >>= 8;
|
|
}
|
|
}
|
|
else if (data->mType == DT_CONST_FUNCTION)
|
|
{
|
|
if (data->mVarIndex < 0)
|
|
{
|
|
InterCodeProcedure* cproc = this->TranslateProcedure(mod, data->mValue, data);
|
|
cproc->ReduceTemporaries();
|
|
}
|
|
|
|
InterVariable::Reference ref;
|
|
ref.mAddr = offset;
|
|
ref.mLower = true;
|
|
ref.mUpper = true;
|
|
ref.mFunction = true;
|
|
ref.mIndex = data->mVarIndex;
|
|
ref.mOffset = 0;
|
|
references.Push(ref);
|
|
}
|
|
else if (data->mType == DT_CONST_POINTER)
|
|
{
|
|
Expression* exp = data->mValue;
|
|
Declaration* dec = exp->mDecValue;
|
|
|
|
InterVariable::Reference ref;
|
|
ref.mAddr = offset;
|
|
ref.mLower = true;
|
|
ref.mUpper = true;
|
|
switch (dec->mType)
|
|
{
|
|
case DT_CONST_DATA:
|
|
{
|
|
if (dec->mVarIndex < 0)
|
|
{
|
|
dec->mVarIndex = mod->mGlobalVars.Size();
|
|
InterVariable var;
|
|
var.mIndex = dec->mVarIndex;
|
|
var.mOffset = 0;
|
|
var.mSize = dec->mSize;
|
|
var.mData = dec->mData;
|
|
var.mIdent = dec->mIdent;
|
|
mod->mGlobalVars.Push(var);
|
|
}
|
|
ref.mFunction = false;
|
|
ref.mIndex = dec->mVarIndex;
|
|
ref.mOffset = 0;
|
|
references.Push(ref);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void InterCodeGenerator::TranslateLogic(Declaration* procType, InterCodeProcedure* proc, InterCodeBasicBlock* block, InterCodeBasicBlock* tblock, InterCodeBasicBlock* fblock, Expression* exp)
|
|
{
|
|
switch (exp->mType)
|
|
{
|
|
case EX_LOGICAL_NOT:
|
|
TranslateLogic(procType, proc, block, fblock, tblock, exp->mLeft);
|
|
break;
|
|
case EX_LOGICAL_AND:
|
|
{
|
|
InterCodeBasicBlock* ablock = new InterCodeBasicBlock();
|
|
proc->Append(ablock);
|
|
TranslateLogic(procType, proc, block, ablock, fblock, exp->mLeft);
|
|
TranslateLogic(procType, proc, ablock, tblock, fblock, exp->mRight);
|
|
break;
|
|
}
|
|
case EX_LOGICAL_OR:
|
|
{
|
|
InterCodeBasicBlock* oblock = new InterCodeBasicBlock();
|
|
proc->Append(oblock);
|
|
TranslateLogic(procType, proc, block, tblock, oblock, exp->mLeft);
|
|
TranslateLogic(procType, proc, oblock, tblock, fblock, exp->mRight);
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
ExValue vr = TranslateExpression(procType, proc, block, exp, nullptr, nullptr);
|
|
vr = Dereference(proc, block, vr);
|
|
|
|
InterInstruction ins;
|
|
ins.mCode = IC_BRANCH;
|
|
ins.mSType[0] = IT_BOOL;
|
|
ins.mSTemp[0] = vr.mTemp;
|
|
block->Append(ins);
|
|
|
|
block->Close(tblock, fblock);
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
InterCodeProcedure* InterCodeGenerator::TranslateProcedure(InterCodeModule * mod, Expression* exp, Declaration * dec)
|
|
{
|
|
InterCodeProcedure* proc = new InterCodeProcedure(mod, dec->mLocation, dec->mIdent);
|
|
dec->mVarIndex = proc->mID;
|
|
|
|
if (mForceNativeCode)
|
|
dec->mFlags |= DTF_NATIVE;
|
|
|
|
if (dec->mFlags & DTF_NATIVE)
|
|
proc->mNativeProcedure = true;
|
|
|
|
InterCodeBasicBlock* entryBlock = new InterCodeBasicBlock();
|
|
|
|
proc->Append(entryBlock);
|
|
|
|
InterCodeBasicBlock* exitBlock = entryBlock;
|
|
|
|
if (dec->mFlags & DTF_DEFINED)
|
|
TranslateExpression(dec->mBase, proc, exitBlock, exp, nullptr, nullptr);
|
|
else
|
|
mErrors->Error(dec->mLocation, "Calling undefined function", dec->mIdent->mString);
|
|
|
|
InterInstruction ins;
|
|
ins.mCode = IC_RETURN;
|
|
exitBlock->Append(ins);
|
|
exitBlock->Close(nullptr, nullptr);
|
|
|
|
_CrtCheckMemory();
|
|
|
|
proc->Close();
|
|
|
|
return proc;
|
|
}
|