mirror of https://github.com/AxioDL/metaforce.git
Work on Frontend
This commit is contained in:
parent
32bd32b9dd
commit
96b8c4c8d8
|
@ -81,19 +81,7 @@ struct IR
|
|||
OpSwizzle /**< Vector insertion/extraction/swizzling operation */
|
||||
};
|
||||
|
||||
enum RegType
|
||||
{
|
||||
RegNone,
|
||||
RegFloat,
|
||||
RegVec3,
|
||||
RegVec4
|
||||
};
|
||||
|
||||
struct RegID
|
||||
{
|
||||
RegType m_type = RegNone;
|
||||
unsigned m_idx = 0;
|
||||
};
|
||||
using RegID = int;
|
||||
|
||||
struct Instruction
|
||||
{
|
||||
|
@ -101,7 +89,7 @@ struct IR
|
|||
|
||||
struct
|
||||
{
|
||||
std::vector<RegID> m_callRegs;
|
||||
std::string m_name;
|
||||
RegID m_target;
|
||||
} m_call;
|
||||
|
||||
|
@ -111,16 +99,18 @@ struct IR
|
|||
RegID m_target;
|
||||
} m_loadImm;
|
||||
|
||||
enum ArithmeticOpType
|
||||
{
|
||||
ArithmeticOpNone,
|
||||
ArithmeticOpAdd,
|
||||
ArithmeticOpSubtract,
|
||||
ArithmeticOpMultiply,
|
||||
ArithmeticOpDivide
|
||||
};
|
||||
|
||||
struct
|
||||
{
|
||||
enum ArithmeticOpType
|
||||
{
|
||||
ArithmeticOpNone,
|
||||
ArithmeticOpAdd,
|
||||
ArithmeticOpSubtract,
|
||||
ArithmeticOpMultiply,
|
||||
ArithmeticOpDivide
|
||||
} m_op = ArithmeticOpNone;
|
||||
ArithmeticOpType m_op = ArithmeticOpNone;
|
||||
RegID m_a;
|
||||
RegID m_b;
|
||||
RegID m_target;
|
||||
|
@ -128,16 +118,15 @@ struct IR
|
|||
|
||||
struct
|
||||
{
|
||||
RegID m_source;
|
||||
int m_sourceIdxs[4] = {-1};
|
||||
RegID m_reg;
|
||||
int m_idxs[4] = {-1};
|
||||
RegID m_target;
|
||||
int m_targetIdxs[4] = {-1};
|
||||
} m_swizzle;
|
||||
|
||||
Instruction(OpType type) : m_op(type) {}
|
||||
};
|
||||
|
||||
unsigned m_floatRegCount = 0;
|
||||
unsigned m_vec3RegCount = 0;
|
||||
unsigned m_vec4RegCount = 0;
|
||||
int m_regCount = 0;
|
||||
std::vector<Instruction> m_instructions;
|
||||
};
|
||||
|
||||
|
@ -164,6 +153,17 @@ class Lexer
|
|||
/* Final lexed root function (IR comes from this) */
|
||||
OperationNode* m_root = nullptr;
|
||||
|
||||
/* Helper for relinking operator precedence */
|
||||
static void ReconnectArithmetic(OperationNode* sn, OperationNode** lastSub, OperationNode** newSub);
|
||||
|
||||
/* Recursive IR compile funcs */
|
||||
static void RecursiveFuncCompile(IR& ir, const Lexer::OperationNode* funcNode, IR::RegID target);
|
||||
static void RecursiveGroupCompile(IR& ir, const Lexer::OperationNode* groupNode, IR::RegID target);
|
||||
static void EmitVec3(IR& ir, const Lexer::OperationNode* funcNode, IR::RegID target);
|
||||
static void EmitVec4(IR& ir, const Lexer::OperationNode* funcNode, IR::RegID target);
|
||||
static void EmitArithmetic(IR& ir, const Lexer::OperationNode* arithNode, IR::RegID target);
|
||||
static void EmitVectorSwizzle(IR& ir, const Lexer::OperationNode* swizNode, IR::RegID target);
|
||||
|
||||
public:
|
||||
void reset();
|
||||
void consumeAllTokens(Parser& parser);
|
||||
|
|
|
@ -1,11 +1,52 @@
|
|||
#include "HECL/HECL.hpp"
|
||||
#include "HECL/Frontend.hpp"
|
||||
|
||||
/* Combined lexer and semantic analysis system */
|
||||
|
||||
namespace HECL
|
||||
{
|
||||
namespace Frontend
|
||||
{
|
||||
|
||||
static IR::Instruction::ArithmeticOpType ArithType(int aChar)
|
||||
{
|
||||
switch (aChar)
|
||||
{
|
||||
case '+':
|
||||
return IR::Instruction::ArithmeticOpAdd;
|
||||
case '-':
|
||||
return IR::Instruction::ArithmeticOpSubtract;
|
||||
case '*':
|
||||
return IR::Instruction::ArithmeticOpMultiply;
|
||||
case '/':
|
||||
return IR::Instruction::ArithmeticOpDivide;
|
||||
default:
|
||||
return IR::Instruction::ArithmeticOpNone;
|
||||
}
|
||||
}
|
||||
|
||||
void Lexer::ReconnectArithmetic(OperationNode* sn, OperationNode** lastSub, OperationNode** newSub)
|
||||
{
|
||||
sn->m_sub = sn->m_prev;
|
||||
sn->m_prev = nullptr;
|
||||
sn->m_sub->m_prev = nullptr;
|
||||
|
||||
sn->m_sub->m_next = sn->m_next;
|
||||
sn->m_next = sn->m_next->m_next;
|
||||
sn->m_sub->m_next->m_prev = sn->m_sub;
|
||||
sn->m_sub->m_next->m_next = nullptr;
|
||||
|
||||
if (*lastSub)
|
||||
{
|
||||
(*lastSub)->m_next = sn;
|
||||
sn->m_prev = *lastSub;
|
||||
}
|
||||
*lastSub = sn;
|
||||
|
||||
if (!*newSub)
|
||||
*newSub = sn;
|
||||
}
|
||||
|
||||
void Lexer::reset()
|
||||
{
|
||||
m_root = nullptr;
|
||||
|
@ -237,29 +278,391 @@ void Lexer::consumeAllTokens(Parser& parser)
|
|||
}
|
||||
}
|
||||
|
||||
/* Organize arithmetic usage into tree-hierarchy */
|
||||
for (Lexer::OperationNode& n : m_pool)
|
||||
{
|
||||
if (n.m_tok.m_type == Parser::TokenEvalGroupStart)
|
||||
{
|
||||
Lexer::OperationNode* newSub = nullptr;
|
||||
Lexer::OperationNode* lastSub = nullptr;
|
||||
for (Lexer::OperationNode* sn = n.m_sub ; sn ; sn = sn->m_next)
|
||||
{
|
||||
if (sn->m_tok.m_type == Parser::TokenArithmeticOp)
|
||||
{
|
||||
IR::Instruction::ArithmeticOpType op = ArithType(sn->m_tok.m_tokenInt);
|
||||
if (op == IR::Instruction::ArithmeticOpMultiply ||
|
||||
op == IR::Instruction::ArithmeticOpDivide)
|
||||
ReconnectArithmetic(sn, &lastSub, &newSub);
|
||||
}
|
||||
}
|
||||
for (Lexer::OperationNode* sn = n.m_sub ; sn ; sn = sn->m_next)
|
||||
{
|
||||
if (sn->m_tok.m_type == Parser::TokenArithmeticOp)
|
||||
{
|
||||
IR::Instruction::ArithmeticOpType op = ArithType(sn->m_tok.m_tokenInt);
|
||||
if (op == IR::Instruction::ArithmeticOpAdd ||
|
||||
op == IR::Instruction::ArithmeticOpSubtract)
|
||||
ReconnectArithmetic(sn, &lastSub, &newSub);
|
||||
}
|
||||
}
|
||||
if (newSub)
|
||||
n.m_sub = newSub;
|
||||
}
|
||||
}
|
||||
|
||||
/* Done! */
|
||||
m_root = firstNode->m_next;
|
||||
}
|
||||
|
||||
void Lexer::EmitVec3(IR& ir, const Lexer::OperationNode* funcNode, IR::RegID target)
|
||||
{
|
||||
/* Optimization case: if empty call, emit zero imm load */
|
||||
const Lexer::OperationNode* gn = funcNode->m_sub;
|
||||
if (!gn)
|
||||
{
|
||||
ir.m_instructions.emplace_back(IR::OpLoadImm);
|
||||
ir.m_instructions.back().m_loadImm.m_immVec = {};
|
||||
return;
|
||||
}
|
||||
|
||||
/* Optimization case: if all numeric literals, emit vector imm load */
|
||||
bool opt = true;
|
||||
const Parser::Token* imms[3];
|
||||
for (int i=0 ; i<3 ; ++i)
|
||||
{
|
||||
if (!gn->m_sub || gn->m_sub->m_tok.m_type != Parser::TokenNumLiteral)
|
||||
{
|
||||
opt = false;
|
||||
break;
|
||||
}
|
||||
imms[i] = &gn->m_sub->m_tok;
|
||||
gn = gn->m_next;
|
||||
}
|
||||
if (opt)
|
||||
{
|
||||
ir.m_instructions.emplace_back(IR::OpLoadImm);
|
||||
atVec4f& vec = ir.m_instructions.back().m_loadImm.m_immVec;
|
||||
vec.vec[0] = imms[0]->m_tokenFloat;
|
||||
vec.vec[1] = imms[1]->m_tokenFloat;
|
||||
vec.vec[2] = imms[2]->m_tokenFloat;
|
||||
vec.vec[3] = 0.0;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Otherwise treat as normal function */
|
||||
RecursiveFuncCompile(ir, funcNode, target);
|
||||
}
|
||||
|
||||
void Lexer::EmitVec4(IR& ir, const Lexer::OperationNode* funcNode, IR::RegID target)
|
||||
{
|
||||
/* Optimization case: if empty call, emit zero imm load */
|
||||
const Lexer::OperationNode* gn = funcNode->m_sub;
|
||||
if (!gn)
|
||||
{
|
||||
ir.m_instructions.emplace_back(IR::OpLoadImm);
|
||||
ir.m_instructions.back().m_loadImm.m_immVec = {};
|
||||
return;
|
||||
}
|
||||
|
||||
/* Optimization case: if all numeric literals, emit vector imm load */
|
||||
bool opt = true;
|
||||
const Parser::Token* imms[4];
|
||||
for (int i=0 ; i<4 ; ++i)
|
||||
{
|
||||
if (!gn->m_sub || gn->m_sub->m_tok.m_type != Parser::TokenNumLiteral)
|
||||
{
|
||||
opt = false;
|
||||
break;
|
||||
}
|
||||
imms[i] = &gn->m_sub->m_tok;
|
||||
gn = gn->m_next;
|
||||
}
|
||||
if (opt)
|
||||
{
|
||||
ir.m_instructions.emplace_back(IR::OpLoadImm);
|
||||
atVec4f& vec = ir.m_instructions.back().m_loadImm.m_immVec;
|
||||
vec.vec[0] = imms[0]->m_tokenFloat;
|
||||
vec.vec[1] = imms[1]->m_tokenFloat;
|
||||
vec.vec[2] = imms[2]->m_tokenFloat;
|
||||
vec.vec[3] = imms[3]->m_tokenFloat;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Otherwise treat as normal function */
|
||||
RecursiveFuncCompile(ir, funcNode, target);
|
||||
}
|
||||
|
||||
void Lexer::EmitArithmetic(IR& ir, const Lexer::OperationNode* arithNode, IR::RegID target)
|
||||
{
|
||||
/* Evaluate operands */
|
||||
atVec4f* opt[2] = {nullptr};
|
||||
size_t instCount = ir.m_instructions.size();
|
||||
const Lexer::OperationNode* on = arithNode->m_sub;
|
||||
IR::RegID tgt = target;
|
||||
for (int i=0 ; i<2 ; ++i, ++tgt)
|
||||
{
|
||||
const Parser::Token& tok = on->m_tok;
|
||||
switch (tok.m_type)
|
||||
{
|
||||
case Parser::TokenFunctionStart:
|
||||
if (!tok.m_tokenString.compare("vec3"))
|
||||
EmitVec3(ir, on, tgt);
|
||||
else if (!tok.m_tokenString.compare("vec4"))
|
||||
EmitVec4(ir, on, tgt);
|
||||
else
|
||||
RecursiveFuncCompile(ir, on, tgt);
|
||||
break;
|
||||
case Parser::TokenEvalGroupStart:
|
||||
RecursiveGroupCompile(ir, on, tgt);
|
||||
break;
|
||||
case Parser::TokenNumLiteral:
|
||||
{
|
||||
ir.m_instructions.emplace_back(IR::OpLoadImm);
|
||||
IR::Instruction& inst = ir.m_instructions.back();
|
||||
inst.m_loadImm.m_target = tgt;
|
||||
inst.m_loadImm.m_immVec.vec[0] = tok.m_tokenFloat;
|
||||
inst.m_loadImm.m_immVec.vec[1] = tok.m_tokenFloat;
|
||||
inst.m_loadImm.m_immVec.vec[2] = tok.m_tokenFloat;
|
||||
inst.m_loadImm.m_immVec.vec[3] = tok.m_tokenFloat;
|
||||
break;
|
||||
}
|
||||
case Parser::TokenVectorSwizzle:
|
||||
EmitVectorSwizzle(ir, on, tgt);
|
||||
break;
|
||||
default:
|
||||
LogModule.report(LogVisor::FatalError, "invalid lexer node for IR");
|
||||
break;
|
||||
};
|
||||
if (ir.m_instructions.back().m_op == IR::OpLoadImm)
|
||||
opt[i] = &ir.m_instructions.back().m_loadImm.m_immVec;
|
||||
on = on->m_next;
|
||||
}
|
||||
|
||||
/* Optimization case: if both operands imm load, pre-evalulate */
|
||||
if (opt[0] && opt[1] && (ir.m_instructions.size() - instCount == 2))
|
||||
{
|
||||
atVec4f eval;
|
||||
switch (ArithType(arithNode->m_tok.m_tokenInt))
|
||||
{
|
||||
case IR::Instruction::ArithmeticOpAdd:
|
||||
eval.vec[0] = opt[0]->vec[0] + opt[1]->vec[0];
|
||||
eval.vec[1] = opt[0]->vec[1] + opt[1]->vec[1];
|
||||
eval.vec[2] = opt[0]->vec[2] + opt[1]->vec[2];
|
||||
eval.vec[3] = opt[0]->vec[3] + opt[1]->vec[3];
|
||||
break;
|
||||
case IR::Instruction::ArithmeticOpSubtract:
|
||||
eval.vec[0] = opt[0]->vec[0] - opt[1]->vec[0];
|
||||
eval.vec[1] = opt[0]->vec[1] - opt[1]->vec[1];
|
||||
eval.vec[2] = opt[0]->vec[2] - opt[1]->vec[2];
|
||||
eval.vec[3] = opt[0]->vec[3] - opt[1]->vec[3];
|
||||
break;
|
||||
case IR::Instruction::ArithmeticOpMultiply:
|
||||
eval.vec[0] = opt[0]->vec[0] * opt[1]->vec[0];
|
||||
eval.vec[1] = opt[0]->vec[1] * opt[1]->vec[1];
|
||||
eval.vec[2] = opt[0]->vec[2] * opt[1]->vec[2];
|
||||
eval.vec[3] = opt[0]->vec[3] * opt[1]->vec[3];
|
||||
break;
|
||||
case IR::Instruction::ArithmeticOpDivide:
|
||||
eval.vec[0] = opt[0]->vec[0] / opt[1]->vec[0];
|
||||
eval.vec[1] = opt[0]->vec[1] / opt[1]->vec[1];
|
||||
eval.vec[2] = opt[0]->vec[2] / opt[1]->vec[2];
|
||||
eval.vec[3] = opt[0]->vec[3] / opt[1]->vec[3];
|
||||
break;
|
||||
default:
|
||||
LogModule.report(LogVisor::FatalError, "invalid arithmetic type");
|
||||
break;
|
||||
}
|
||||
ir.m_instructions.pop_back();
|
||||
ir.m_instructions.pop_back();
|
||||
ir.m_instructions.emplace_back(IR::OpLoadImm);
|
||||
IR::Instruction& inst = ir.m_instructions.back();
|
||||
inst.m_loadImm.m_target = target;
|
||||
inst.m_loadImm.m_immVec = eval;
|
||||
}
|
||||
else
|
||||
{
|
||||
ir.m_instructions.emplace_back(IR::OpArithmetic);
|
||||
IR::Instruction& inst = ir.m_instructions.back();
|
||||
inst.m_arithmetic.m_target = target;
|
||||
inst.m_arithmetic.m_a = target;
|
||||
inst.m_arithmetic.m_b = target + 1;
|
||||
inst.m_arithmetic.m_op = ArithType(arithNode->m_tok.m_tokenInt);
|
||||
if (tgt > ir.m_regCount)
|
||||
ir.m_regCount = tgt;
|
||||
}
|
||||
}
|
||||
|
||||
static int SwizzleCompIdx(char aChar)
|
||||
{
|
||||
switch (aChar)
|
||||
{
|
||||
case 'x':
|
||||
case 'r':
|
||||
return 0;
|
||||
case 'y':
|
||||
case 'g':
|
||||
return 1;
|
||||
case 'z':
|
||||
case 'b':
|
||||
return 2;
|
||||
case 'w':
|
||||
case 'a':
|
||||
return 3;
|
||||
default:
|
||||
LogModule.report(LogVisor::FatalError, "invalid swizzle char %c", aChar);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void Lexer::EmitVectorSwizzle(IR& ir, const Lexer::OperationNode* swizNode, IR::RegID target)
|
||||
{
|
||||
const std::string& str = swizNode->m_tok.m_tokenString;
|
||||
if (str.size() != 1 && str.size() != 3 && str.size() != 4)
|
||||
LogModule.report(LogVisor::FatalError, "%d component swizzles not supported", int(str.size()));
|
||||
|
||||
size_t instCount = ir.m_instructions.size();
|
||||
const Lexer::OperationNode* on = swizNode->m_sub;
|
||||
const Parser::Token& tok = on->m_tok;
|
||||
switch (tok.m_type)
|
||||
{
|
||||
case Parser::TokenFunctionStart:
|
||||
if (!tok.m_tokenString.compare("vec3"))
|
||||
EmitVec3(ir, on, target);
|
||||
else if (!tok.m_tokenString.compare("vec4"))
|
||||
EmitVec4(ir, on, target);
|
||||
else
|
||||
RecursiveFuncCompile(ir, on, target);
|
||||
break;
|
||||
case Parser::TokenEvalGroupStart:
|
||||
RecursiveGroupCompile(ir, on, target);
|
||||
break;
|
||||
case Parser::TokenNumLiteral:
|
||||
{
|
||||
ir.m_instructions.emplace_back(IR::OpLoadImm);
|
||||
IR::Instruction& inst = ir.m_instructions.back();
|
||||
inst.m_loadImm.m_target = target;
|
||||
inst.m_loadImm.m_immVec.vec[0] = tok.m_tokenFloat;
|
||||
inst.m_loadImm.m_immVec.vec[1] = tok.m_tokenFloat;
|
||||
inst.m_loadImm.m_immVec.vec[2] = tok.m_tokenFloat;
|
||||
inst.m_loadImm.m_immVec.vec[3] = tok.m_tokenFloat;
|
||||
break;
|
||||
}
|
||||
case Parser::TokenVectorSwizzle:
|
||||
EmitVectorSwizzle(ir, on, target);
|
||||
break;
|
||||
default:
|
||||
LogModule.report(LogVisor::FatalError, "invalid lexer node for IR");
|
||||
break;
|
||||
};
|
||||
|
||||
/* Optimization case: if operand imm load, pre-evalulate */
|
||||
if (ir.m_instructions.back().m_op == IR::OpLoadImm && (ir.m_instructions.size() - instCount == 1))
|
||||
{
|
||||
atVec4f* opt = &ir.m_instructions.back().m_loadImm.m_immVec;
|
||||
atVec4f eval;
|
||||
switch (str.size())
|
||||
{
|
||||
case 1:
|
||||
eval = {opt->vec[SwizzleCompIdx(str[0])]};
|
||||
break;
|
||||
case 3:
|
||||
eval.vec[0] = opt->vec[SwizzleCompIdx(str[0])];
|
||||
eval.vec[1] = opt->vec[SwizzleCompIdx(str[1])];
|
||||
eval.vec[2] = opt->vec[SwizzleCompIdx(str[2])];
|
||||
eval.vec[3] = 0.0;
|
||||
break;
|
||||
case 4:
|
||||
eval.vec[0] = opt->vec[SwizzleCompIdx(str[0])];
|
||||
eval.vec[1] = opt->vec[SwizzleCompIdx(str[1])];
|
||||
eval.vec[2] = opt->vec[SwizzleCompIdx(str[2])];
|
||||
eval.vec[3] = opt->vec[SwizzleCompIdx(str[3])];
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
ir.m_instructions.pop_back();
|
||||
ir.m_instructions.emplace_back(IR::OpLoadImm);
|
||||
IR::Instruction& inst = ir.m_instructions.back();
|
||||
inst.m_loadImm.m_target = target;
|
||||
inst.m_loadImm.m_immVec = eval;
|
||||
}
|
||||
else
|
||||
{
|
||||
ir.m_instructions.emplace_back(IR::OpSwizzle);
|
||||
IR::Instruction& inst = ir.m_instructions.back();
|
||||
inst.m_swizzle.m_reg = target;
|
||||
inst.m_swizzle.m_target = target;
|
||||
for (int i=0 ; i<str.size() ; ++i)
|
||||
inst.m_swizzle.m_idxs[i] = SwizzleCompIdx(str[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void Lexer::RecursiveGroupCompile(IR& ir, const Lexer::OperationNode* groupNode, IR::RegID target)
|
||||
{
|
||||
IR::RegID tgt = target;
|
||||
for (const Lexer::OperationNode* sn = groupNode->m_sub ; sn ; sn = sn->m_next, ++tgt)
|
||||
{
|
||||
const Parser::Token& tok = sn->m_tok;
|
||||
switch (tok.m_type)
|
||||
{
|
||||
case Parser::TokenFunctionStart:
|
||||
if (!tok.m_tokenString.compare("vec3"))
|
||||
EmitVec3(ir, sn, tgt);
|
||||
else if (!tok.m_tokenString.compare("vec4"))
|
||||
EmitVec4(ir, sn, tgt);
|
||||
else
|
||||
RecursiveFuncCompile(ir, sn, tgt);
|
||||
break;
|
||||
case Parser::TokenEvalGroupStart:
|
||||
RecursiveGroupCompile(ir, sn, tgt);
|
||||
break;
|
||||
case Parser::TokenNumLiteral:
|
||||
{
|
||||
ir.m_instructions.emplace_back(IR::OpLoadImm);
|
||||
IR::Instruction& inst = ir.m_instructions.back();
|
||||
inst.m_loadImm.m_target = tgt;
|
||||
inst.m_loadImm.m_immVec.vec[0] = tok.m_tokenFloat;
|
||||
inst.m_loadImm.m_immVec.vec[1] = tok.m_tokenFloat;
|
||||
inst.m_loadImm.m_immVec.vec[2] = tok.m_tokenFloat;
|
||||
inst.m_loadImm.m_immVec.vec[3] = tok.m_tokenFloat;
|
||||
break;
|
||||
}
|
||||
case Parser::TokenArithmeticOp:
|
||||
EmitArithmetic(ir, sn, tgt);
|
||||
break;
|
||||
case Parser::TokenVectorSwizzle:
|
||||
EmitVectorSwizzle(ir, sn, tgt);
|
||||
break;
|
||||
default:
|
||||
LogModule.report(LogVisor::FatalError, "invalid lexer node for IR");
|
||||
break;
|
||||
};
|
||||
}
|
||||
if (tgt > ir.m_regCount)
|
||||
ir.m_regCount = tgt;
|
||||
}
|
||||
|
||||
void Lexer::RecursiveFuncCompile(IR& ir, const Lexer::OperationNode* funcNode, IR::RegID target)
|
||||
{
|
||||
IR::RegID tgt = target;
|
||||
for (const Lexer::OperationNode* gn = funcNode->m_sub ; gn ; gn = gn->m_next, ++tgt)
|
||||
RecursiveGroupCompile(ir, gn, tgt);
|
||||
ir.m_instructions.emplace_back(IR::OpCall);
|
||||
IR::Instruction& inst = ir.m_instructions.back();
|
||||
inst.m_call.m_name = funcNode->m_tok.m_tokenString;
|
||||
inst.m_call.m_target = target;
|
||||
if (tgt > ir.m_regCount)
|
||||
ir.m_regCount = tgt;
|
||||
}
|
||||
|
||||
IR Lexer::compileIR() const
|
||||
{
|
||||
if (!m_root)
|
||||
LogModule.report(LogVisor::FatalError, "unable to compile HECL-IR for invalid source");
|
||||
|
||||
IR ir;
|
||||
|
||||
/* Determine maximum float regs */
|
||||
for (const Lexer::OperationNode& n : m_pool)
|
||||
{
|
||||
if (n.m_tok.m_type == Parser::TokenFunctionStart)
|
||||
{
|
||||
for (Lexer::OperationNode* sn = n.m_sub ; sn ; sn = sn->m_next)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RecursiveFuncCompile(ir, m_root, 0);
|
||||
return ir;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include "HECL/HECL.hpp"
|
||||
#include "HECL/Frontend.hpp"
|
||||
#include <math.h>
|
||||
|
||||
/* Syntatical token parsing system */
|
||||
|
||||
namespace HECL
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue