std::shared_ptr<cs6300::BasicBlock> cs6300::CallExpression::emit() const { auto result = std::make_shared<BasicBlock>(); result->instructions.push_back(ThreeAddressInstruction( ThreeAddressInstruction::StoreFrame, 0, 0, 0)); for(auto&& arg:actualArguments) { auto code = arg->emit(); std::copy(code->instructions.begin(), code->instructions.end(), std::back_inserter(result->instructions)); result->instructions.emplace_back(ThreeAddressInstruction::CopyArgument, 0 /*TODO:Placeholder for argument*/, arg->getLabel(), 0); } result->instructions.push_back(ThreeAddressInstruction( ThreeAddressInstruction::CallFunction, 0, funcLabel, 0)); // set fp and jump result->instructions.push_back(ThreeAddressInstruction( ThreeAddressInstruction::Return, getLabel(), 0, 0)); // get return value into register // TODO: move sp back according to arguments size result->instructions.push_back(ThreeAddressInstruction( ThreeAddressInstruction::RestoreFrame, 0, 0, 0)); return result; }
cs6300::FlowGraph cs6300::Write::emit() { auto block = std::make_shared<BasicBlock>(); block->instructions.push_back( ThreeAddressInstruction("Begin Write", file, line)); for (auto&& val : values) { auto b = val->emit(); std::copy(b->instructions.begin(), b->instructions.end(), std::back_inserter(block->instructions)); auto type = val->type(); auto rtype = std::dynamic_pointer_cast<ReferenceType>(type); if (rtype) type = rtype->type; if (type == BuiltInType::getInt()) { block->instructions.push_back(ThreeAddressInstruction( ThreeAddressInstruction::WriteInt, 0, val->getLabel(), 0)); } else if (type == BuiltInType::getChar()) { block->instructions.push_back(ThreeAddressInstruction( ThreeAddressInstruction::WriteChar, 0, val->getLabel(), 0)); } else if (type == BuiltInType::getBool()) { block->instructions.push_back(ThreeAddressInstruction( ThreeAddressInstruction::WriteBool, 0, val->getLabel(), 0)); } else if (type == BuiltInType::getStr()) { block->instructions.push_back(ThreeAddressInstruction( ThreeAddressInstruction::WriteStr, 0, val->value(), 0)); } else { if (type) LOG(FATAL) << "Unsupported print type " << type->name() << " " << val->name(); else LOG(FATAL) << "Unsupported print type NULL"; } } block->instructions.push_back(ThreeAddressInstruction("End Write")); return std::make_pair(block, block); }
std::shared_ptr<cs6300::BasicBlock> cs6300::CallExpression::emit() const { auto result = std::make_shared<BasicBlock>(); for (auto&& arg : actualArguments) { auto code = arg->emit(); std::copy(code->instructions.begin(), code->instructions.end(), std::back_inserter(result->instructions)); } int stack_offset = -symbolTable->stackSpace(); result->instructions.push_back(ThreeAddressInstruction( ThreeAddressInstruction::StoreFrame, 0, stack_offset, 0)); int offset = 0; for (auto&& arg : actualArguments) { offset -= arg->type()->size(); if (std::dynamic_pointer_cast<ArrayType>(arg->type()) || std::dynamic_pointer_cast<RecordType>(arg->type())) { auto tlabel = Expression::getNextLabel(); result->instructions.emplace_back(ThreeAddressInstruction( "Deep copying. Size " + std::to_string(arg->type()->size()))); int max = arg->type()->size() / 4; for (int i = 0; i < max; i++) { result->instructions.emplace_back( ThreeAddressInstruction::LoadMemory, tlabel, arg->getLabel(), i * 4); result->instructions.emplace_back(ThreeAddressInstruction::CopyArgument, cs6300::STACK, tlabel, offset + i * 4); } } else { result->instructions.emplace_back(ThreeAddressInstruction::CopyArgument, cs6300::STACK, arg->getLabel(), offset); } } result->instructions.push_back( ThreeAddressInstruction(ThreeAddressInstruction::CallFunction, 0, funcLabel, offset)); // set fp and jump result->instructions.push_back(ThreeAddressInstruction( ThreeAddressInstruction::RestoreFrame, 0, stack_offset, 0)); result->instructions.push_back( ThreeAddressInstruction(ThreeAddressInstruction::Return, getLabel(), 0, 0)); // get return value into register return result; }