RE: A small C compiler generating Eigen IR ยป codegen.patch
ecc/codegen.cpp | ||
---|---|---|
case ND_VAR:
|
||
// Variable-length array, which is always local.
|
||
if (node->var->ty->kind == TY_VLA) {
|
||
r0 = e->Move(Code::Reg(types[ptr],Code::RFP, node->var->offset)); // mov ptr $0, ptr $fp%+d"
|
||
r0 = (Code::Reg(types[ptr],Code::RFP, node->var->offset)); // mov ptr $0, ptr $fp%+d"
|
||
return;
|
||
}
|
||
// Local variable
|
||
if (node->var->is_local) {
|
||
r0 = e->Move(Code::Reg(types[ptr],Code::RFP, node->var->offset)); // mov ptr $0, ptr $fp%+d"
|
||
r0 = (Code::Reg(types[ptr],Code::RFP, node->var->offset)); // mov ptr $0, ptr $fp%+d"
|
||
return;
|
||
}
|
||
... | ... | |
#endif
|
||
// Function
|
||
if (node->ty->kind == TY_FUNC) {
|
||
r0 = e->Move(Code::Adr(types[fun],node->var->name)); // mov fun $0, fun @%s
|
||
r0 = (Code::Adr(types[fun],node->var->name)); // mov fun $0, fun @%s
|
||
return;
|
||
}
|
||
// Global variable
|
||
r0 = e->Move(Code::Adr(types[ptr],node->var->name)); // mov ptr $0, ptr @%s
|
||
r0 = (Code::Adr(types[ptr],node->var->name)); // mov ptr $0, ptr @%s
|
||
return;
|
||
case ND_DEREF:
|
||
gen_expr(node->lhs);
|
||
... | ... | |
}
|
||
break;
|
||
case ND_VLA_PTR:
|
||
r0 = e->Move(Code::Reg(types[ptr], Code::RFP,node->var->offset)); // mov ptr $0, ptr $fp%+d
|
||
r0 = (Code::Reg(types[ptr], Code::RFP,node->var->offset)); // mov ptr $0, ptr $fp%+d
|
||
return;
|
||
}
|
||
... | ... | |
}
|
||
const Code::Type type = getCodeType(ty);
|
||
r0 = e->MakeRegister(e->MakeMemory(type,r0)); // mov %s $0, %s [$0]
|
||
r0 = (e->MakeMemory(type,r0)); // mov %s $0, %s [$0]
|
||
// like Move, but reuses the register of r0 instead of allocating another one and really move
|
||
}
|
||
// Store $0 to the address on top of the stack
|
||
static void store(Type *ty) {
|
||
Smop tmpReg = pop(types[ptr]);
|
||
static void store(Type *ty, const Smop& tmpReg) {
|
||
switch (ty->kind) {
|
||
case TY_STRUCT:
|
||
... | ... | |
if (to->kind == TY_BOOL) {
|
||
Code::Type type = getCodeType(from);
|
||
Code::Emitter2::Label yes = e->CreateLabel();
|
||
e->BranchEqual(yes,Code::Imm(type,0),reg); // breq +2, %s 0, %s %s", type, type, reg
|
||
type = getCodeType(to);
|
||
reg = e->Move(Code::Imm(type,0)); // mov %s %s, %s 0", type, reg, type
|
||
Code::Emitter2::Label end = e->CreateLabel();
|
||
e->Branch(end); // br +1
|
||
yes();
|
||
reg = e->Move(Code::Imm(type,1)); // mov %s %s, %s 1", type, reg, type
|
||
end();
|
||
e->BranchNotEqual(yes,Code::Imm(type,0),reg); // breq +2, %s 0, %s %s", type, type, reg
|
||
r0 = e->Set (yes, Code::Imm(type,0), Code::Imm(type,1));
|
||
return;
|
||
}
|
||
... | ... | |
// If the return type is a large struct/union, the caller passes
|
||
// a pointer to a buffer as if it were the first argument.
|
||
if (node->ret_buffer) {
|
||
r0 = e->Move(Code::Reg(types[ptr], Code::RFP,node->ret_buffer->offset)); // mov ptr $0, ptr $fp%+d
|
||
r0 = Code::Reg(types[ptr], Code::RFP,node->ret_buffer->offset); // mov ptr $0, ptr $fp%+d
|
||
pushRes(types[ptr]);
|
||
stack++;
|
||
}
|
||
... | ... | |
case TY_FLOAT:
|
||
case TY_DOUBLE:
|
||
case TY_LDOUBLE: {
|
||
r0 = e->Move(Code::FImm(ty,node->fval)); // mov %s $0, %s %Lf
|
||
r0 = (Code::FImm(ty,node->fval)); // mov %s $0, %s %Lf
|
||
return;
|
||
}
|
||
}
|
||
r0 = e->Move(Code::Imm(ty,node->val)); // mov %s $0, %s %Ld
|
||
r0 = (Code::Imm(ty,node->val)); // mov %s $0, %s %Ld
|
||
return;
|
||
}
|
||
case ND_NEG: {
|
||
... | ... | |
gen_addr(node->lhs);
|
||
return;
|
||
case ND_ASSIGN:
|
||
case ND_ASSIGN: {
|
||
gen_addr(node->lhs);
|
||
pushRes(types[ptr]);
|
||
auto lhs = std::move (r0);
|
||
gen_expr(node->rhs);
|
||
if (node->lhs->kind == ND_MEMBER && node->lhs->member->is_bitfield) {
|
||
... | ... | |
r9 = e->Move(Code::Imm(mty,~mask)); // mov %s %s, %s %ld
|
||
r0 = e->And(e->Convert(mty,r0), r9); // and %s $0, %s $0, %s %s
|
||
r0 = e->Or(r0, rdi); // or %s $0, %s $0, %s %s
|
||
store(node->ty);
|
||
store(node->ty, lhs);
|
||
// restore from r8:
|
||
r0 = e->Move(r8); // mov %s $0, %s %s
|
||
return;
|
||
}else {
|
||
store(node->ty);
|
||
store(node->ty, lhs);
|
||
return;
|
||
}
|
||
}
|
||
case ND_STMT_EXPR:
|
||
for (Node *n = node->body; n; n = n->next)
|
||
... | ... | |
return;
|
||
case ND_MEMZERO:
|
||
r0 = e->Move(Code::Reg(types[ptr],Code::RFP,node->var->offset)); // mov ptr $0, ptr $fp%+d
|
||
r0 = (Code::Reg(types[ptr],Code::RFP,node->var->offset)); // mov ptr $0, ptr $fp%+d
|
||
e->Fill(r0,Code::Imm(types[ptr],node->var->ty->size), Code::Imm(types[u1],0)); // fill ptr $0, ptr %d, u1 0
|
||
return;
|
||
case ND_COND: {
|
||
... | ... | |
if( ret )
|
||
{
|
||
const Code::Type type = getCodeType(ret);
|
||
r0 = e->Move(Code::Reg(type,Code::RRes)); // mov %s $0, %s $res
|
||
r0 = (Code::Reg(type,Code::RRes)); // mov %s $0, %s $res
|
||
}
|
||
depth -= stack_slots;
|
||
... | ... | |
case TY_UNION:
|
||
copy_struct_mem();
|
||
break;
|
||
case TY_VOID:
|
||
case TY_VLA:
|
||
break;
|
||
default:
|
||
e->Move (Code::Reg {getCodeType(ty), Code::RRes}, r0);
|
||
}
|
||
returnType = getCodeType(ty);
|
||
}
|
||
... | ... | |
{
|
||
Smop res = Code::Reg(returnType,Code::RRes);
|
||
setInt(0,res);
|
||
}else
|
||
e->Move(Code::Reg(returnType,Code::RRes), e->Convert(returnType,r0));
|
||
}
|
||
}
|
||
e->Leave();
|
||
if( isMain )
|
||
{
|
||
pushRes(types[s4]);
|
||
e->Push(Code::Reg {returnType, Code::RRes});
|
||
e->Call(Code::Adr(types[fun],"_Exit"),0); // call fun @_Exit, 0
|
||
}else
|
||
e->Return();
|