void LegalizeMD::LegalizeDst(IR::Instr * instr, bool fPostRegAlloc) { LegalForms forms = LegalDstForms(instr); IR::Opnd * opnd = instr->GetDst(); if (opnd == NULL) { #ifdef DBG // No legalization possible, just report error. if (forms != 0) { IllegalInstr(instr, L"Expected dst opnd"); } #endif return; } switch (opnd->GetKind()) { case IR::OpndKindReg: #ifdef DBG // No legalization possible, just report error. if (!(forms & L_RegMask)) { IllegalInstr(instr, L"Unexpected reg dst"); } #endif break; case IR::OpndKindMemRef: { // MemRefOpnd is a deference of the memory location. // So extract the location, load it to register, replace the MemRefOpnd with an IndirOpnd taking the // register as base, and fall through to legalize the IndirOpnd. void *memLoc = opnd->AsMemRefOpnd()->GetMemLoc(); IR::RegOpnd *newReg = IR::RegOpnd::New(TyMachPtr, instr->m_func); if (fPostRegAlloc) { newReg->SetReg(SCRATCH_REG); } IR::Instr *newInstr = IR::Instr::New(Js::OpCode::LDIMM, newReg, IR::AddrOpnd::New(memLoc, opnd->AsMemRefOpnd()->GetAddrKind(), instr->m_func, true), instr->m_func); instr->InsertBefore(newInstr); LegalizeMD::LegalizeInstr(newInstr, fPostRegAlloc); IR::IndirOpnd *indirOpnd = IR::IndirOpnd::New(newReg, 0, opnd->GetType(), instr->m_func); opnd = instr->ReplaceDst(indirOpnd); } // FALL THROUGH case IR::OpndKindIndir: if (!(forms & L_IndirMask)) { instr = LegalizeStore(instr, forms, fPostRegAlloc); forms = LegalDstForms(instr); } LegalizeIndirOffset(instr, opnd->AsIndirOpnd(), forms, fPostRegAlloc); break; case IR::OpndKindSym: if (!(forms & L_SymMask)) { instr = LegalizeStore(instr, forms, fPostRegAlloc); forms = LegalDstForms(instr); } if (fPostRegAlloc) { // In order to legalize SymOffset we need to know final argument area, which is only available after lowerer. // So, don't legalize sym offset here, but it will be done as part of register allocator. LegalizeSymOffset(instr, opnd->AsSymOpnd(), forms, fPostRegAlloc); } break; default: AssertMsg(UNREACHED, "Unexpected dst opnd kind"); break; } }