/// runOnMachineFunction - This uses the printMachineInstruction() /// method to print assembly for each instruction. /// bool X86IntelAsmPrinter::runOnMachineFunction(MachineFunction &MF) { SetupMachineFunction(MF); O << "\n\n"; // Print out constants referenced by the function EmitConstantPool(MF.getConstantPool()); // Print out labels for the function. const Function *F = MF.getFunction(); unsigned CC = F->getCallingConv(); // Populate function information map. Actually, We don't want to populate // non-stdcall or non-fastcall functions' information right now. if (CC == CallingConv::X86_StdCall || CC == CallingConv::X86_FastCall) FunctionInfoMap[F] = *MF.getInfo<X86MachineFunctionInfo>(); decorateName(CurrentFnName, F); SwitchToTextSection("_text", F); unsigned FnAlign = 4; if (F->hasFnAttr(Attribute::OptimizeForSize)) FnAlign = 1; switch (F->getLinkage()) { default: assert(0 && "Unsupported linkage type!"); case Function::PrivateLinkage: case Function::InternalLinkage: EmitAlignment(FnAlign); break; case Function::DLLExportLinkage: DLLExportedFns.insert(CurrentFnName); //FALLS THROUGH case Function::ExternalLinkage: O << "\tpublic " << CurrentFnName << "\n"; EmitAlignment(FnAlign); break; } O << CurrentFnName << "\tproc near\n"; // Print out code for the function. for (MachineFunction::const_iterator I = MF.begin(), E = MF.end(); I != E; ++I) { // Print a label for the basic block if there are any predecessors. if (!I->pred_empty()) { printBasicBlockLabel(I, true, true); O << '\n'; } for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end(); II != E; ++II) { // Print the assembly for the instruction. printMachineInstruction(II); } } // Print out jump tables referenced by the function. EmitJumpTableInfo(MF.getJumpTableInfo(), MF); O << CurrentFnName << "\tendp\n"; O.flush(); // We didn't modify anything. return false; }
bool MIRParserImpl::initializeMachineFunction(const yaml::MachineFunction &YamlMF, MachineFunction &MF) { // TODO: Recreate the machine function. initNames2RegClasses(MF); initNames2RegBanks(MF); if (YamlMF.Alignment) MF.setAlignment(YamlMF.Alignment); MF.setExposesReturnsTwice(YamlMF.ExposesReturnsTwice); if (YamlMF.Legalized) MF.getProperties().set(MachineFunctionProperties::Property::Legalized); if (YamlMF.RegBankSelected) MF.getProperties().set( MachineFunctionProperties::Property::RegBankSelected); if (YamlMF.Selected) MF.getProperties().set(MachineFunctionProperties::Property::Selected); PerFunctionMIParsingState PFS(MF, SM, IRSlots, Names2RegClasses, Names2RegBanks); if (parseRegisterInfo(PFS, YamlMF)) return true; if (!YamlMF.Constants.empty()) { auto *ConstantPool = MF.getConstantPool(); assert(ConstantPool && "Constant pool must be created"); if (initializeConstantPool(PFS, *ConstantPool, YamlMF)) return true; } StringRef BlockStr = YamlMF.Body.Value.Value; SMDiagnostic Error; SourceMgr BlockSM; BlockSM.AddNewSourceBuffer( MemoryBuffer::getMemBuffer(BlockStr, "",/*RequiresNullTerminator=*/false), SMLoc()); PFS.SM = &BlockSM; if (parseMachineBasicBlockDefinitions(PFS, BlockStr, Error)) { reportDiagnostic( diagFromBlockStringDiag(Error, YamlMF.Body.Value.SourceRange)); return true; } PFS.SM = &SM; // Initialize the frame information after creating all the MBBs so that the // MBB references in the frame information can be resolved. if (initializeFrameInfo(PFS, YamlMF)) return true; // Initialize the jump table after creating all the MBBs so that the MBB // references can be resolved. if (!YamlMF.JumpTableInfo.Entries.empty() && initializeJumpTableInfo(PFS, YamlMF.JumpTableInfo)) return true; // Parse the machine instructions after creating all of the MBBs so that the // parser can resolve the MBB references. StringRef InsnStr = YamlMF.Body.Value.Value; SourceMgr InsnSM; InsnSM.AddNewSourceBuffer( MemoryBuffer::getMemBuffer(InsnStr, "", /*RequiresNullTerminator=*/false), SMLoc()); PFS.SM = &InsnSM; if (parseMachineInstructions(PFS, InsnStr, Error)) { reportDiagnostic( diagFromBlockStringDiag(Error, YamlMF.Body.Value.SourceRange)); return true; } PFS.SM = &SM; if (setupRegisterInfo(PFS, YamlMF)) return true; computeFunctionProperties(MF); MF.verify(); return false; }
bool MIRParserImpl::initializeMachineFunction(MachineFunction &MF) { auto It = Functions.find(MF.getName()); if (It == Functions.end()) return error(Twine("no machine function information for function '") + MF.getName() + "' in the MIR file"); // TODO: Recreate the machine function. const yaml::MachineFunction &YamlMF = *It->getValue(); if (YamlMF.Alignment) MF.setAlignment(YamlMF.Alignment); MF.setExposesReturnsTwice(YamlMF.ExposesReturnsTwice); if (YamlMF.Legalized) MF.getProperties().set(MachineFunctionProperties::Property::Legalized); if (YamlMF.RegBankSelected) MF.getProperties().set( MachineFunctionProperties::Property::RegBankSelected); if (YamlMF.Selected) MF.getProperties().set(MachineFunctionProperties::Property::Selected); PerFunctionMIParsingState PFS(MF, SM, IRSlots); if (initializeRegisterInfo(PFS, YamlMF)) return true; if (!YamlMF.Constants.empty()) { auto *ConstantPool = MF.getConstantPool(); assert(ConstantPool && "Constant pool must be created"); if (initializeConstantPool(PFS, *ConstantPool, YamlMF)) return true; } StringRef BlockStr = YamlMF.Body.Value.Value; SMDiagnostic Error; SourceMgr BlockSM; BlockSM.AddNewSourceBuffer( MemoryBuffer::getMemBuffer(BlockStr, "",/*RequiresNullTerminator=*/false), SMLoc()); PFS.SM = &BlockSM; if (parseMachineBasicBlockDefinitions(PFS, BlockStr, Error)) { reportDiagnostic( diagFromBlockStringDiag(Error, YamlMF.Body.Value.SourceRange)); return true; } PFS.SM = &SM; if (MF.empty()) return error(Twine("machine function '") + Twine(MF.getName()) + "' requires at least one machine basic block in its body"); // Initialize the frame information after creating all the MBBs so that the // MBB references in the frame information can be resolved. if (initializeFrameInfo(PFS, YamlMF)) return true; // Initialize the jump table after creating all the MBBs so that the MBB // references can be resolved. if (!YamlMF.JumpTableInfo.Entries.empty() && initializeJumpTableInfo(PFS, YamlMF.JumpTableInfo)) return true; // Parse the machine instructions after creating all of the MBBs so that the // parser can resolve the MBB references. StringRef InsnStr = YamlMF.Body.Value.Value; SourceMgr InsnSM; InsnSM.AddNewSourceBuffer( MemoryBuffer::getMemBuffer(InsnStr, "", /*RequiresNullTerminator=*/false), SMLoc()); PFS.SM = &InsnSM; if (parseMachineInstructions(PFS, InsnStr, Error)) { reportDiagnostic( diagFromBlockStringDiag(Error, YamlMF.Body.Value.SourceRange)); return true; } PFS.SM = &SM; inferRegisterInfo(PFS, YamlMF); computeFunctionProperties(MF); // FIXME: This is a temporary workaround until the reserved registers can be // serialized. MF.getRegInfo().freezeReservedRegs(MF); MF.verify(); return false; }
void SVMFrameLowering::emitPrologue(MachineFunction &MF) const { MachineBasicBlock &MBB = MF.front(); MachineBasicBlock::iterator MBBI = MBB.begin(); MachineFrameInfo *MFI = MF.getFrameInfo(); DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); const SVMInstrInfo &TII = *static_cast<const SVMInstrInfo*>(MF.getTarget().getInstrInfo()); /* * Align both the top and bottom of the stack frame, so that our frame * size and frame indices are always word-aligned. */ unsigned stackSize = MFI->getStackSize(); unsigned alignMask = getStackAlignment() - 1; assert(alignMask >= 3); stackSize = (stackSize + alignMask) & ~alignMask; MFI->setStackSize(stackSize); /* * Apply a stack frame adjustment at the beginning of this function. * On SVM, there are three ways to do this. In order of decreasing * preferability: * * 1. We can get a small adjustment (0x7F words or less) for * free as part of the 'call' SVC. This stack adjustment is encoded * into the function address at link time, using a FNSTACK * pseudo-instruction, which is used by SVMELFProgramWriter to * generate the proper relocations. * * 2. Small remainders can be allocated using SPADJ. This works for * up to 31 words at a time. * * 3. Larger remainders are allocated using an indirect addrop which * can allocate up to 64MB of stack space :) * * The addrop in (3) clearly trumps the other two methods for dealing * with truly large stack frames. But because the FNSTACK adjustment is * so cheap, we always try to use it. This also has the nice effect of * making large-stacked functions clearly visible, since they'll have * a 0x7F in their upper address bits. */ uint32_t wordsRemaining = (stackSize + 3) / 4; if (wordsRemaining) { uint32_t chunk = std::min(wordsRemaining, (uint32_t)0x7F); BuildMI(MBB, MBBI, dl, TII.get(SVM::FNSTACK)).addImm(chunk << 2); wordsRemaining -= chunk; } if (wordsRemaining) report_warning(MF.getFunction(), "Large stack frame, " + Twine(stackSize) + " bytes."); if (wordsRemaining > 0x1F) { assert(wordsRemaining <= 0xFFFFFF); uint32_t indir = 0xc3000000 | wordsRemaining; LLVMContext &Ctx = MF.getFunction()->getContext(); Constant *C = ConstantInt::get(Type::getInt32Ty(Ctx), indir); unsigned cpi = MF.getConstantPool()->getConstantPoolIndex(C, 4); BuildMI(MBB, MBBI, dl, TII.get(SVM::SPADJi)).addConstantPoolIndex(cpi); } else if (wordsRemaining) { assert(wordsRemaining <= 0x1F); BuildMI(MBB, MBBI, dl, TII.get(SVM::SPADJ)).addImm(wordsRemaining << 2); } }