X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FCodeGen%2FMIRParser%2FMIRParser.cpp;h=0679ec02c988fe30a399dae74edce260988d2d6b;hb=7a40257530af4fd05cb6d627b7ba0ad25ba66206;hp=fc1f9753309a42fa4bb388e94e2db1a0f41c8db7;hpb=31512fe6ce3b748e5ad5ebd3bd9a6b648621eb52;p=oota-llvm.git diff --git a/lib/CodeGen/MIRParser/MIRParser.cpp b/lib/CodeGen/MIRParser/MIRParser.cpp index fc1f9753309..0679ec02c98 100644 --- a/lib/CodeGen/MIRParser/MIRParser.cpp +++ b/lib/CodeGen/MIRParser/MIRParser.cpp @@ -20,7 +20,9 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/AsmParser/Parser.h" #include "llvm/AsmParser/SlotMapping.h" +#include "llvm/CodeGen/MachineConstantPool.h" #include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/MIRYamlMapping.h" #include "llvm/IR/BasicBlock.h" @@ -48,6 +50,8 @@ class MIRParserImpl { LLVMContext &Context; StringMap> Functions; SlotMapping IRSlots; + /// Maps from register class names to register classes. + StringMap Names2RegClasses; public: MIRParserImpl(std::unique_ptr Contents, StringRef Filename, @@ -99,10 +103,34 @@ public: const yaml::MachineBasicBlock &YamlMBB, const PerFunctionMIParsingState &PFS); - bool initializeRegisterInfo(MachineRegisterInfo &RegInfo, - const yaml::MachineFunction &YamlMF); + bool initializeRegisterInfo(MachineFunction &MF, + const yaml::MachineFunction &YamlMF, + PerFunctionMIParsingState &PFS); + + bool initializeFrameInfo(MachineFunction &MF, + const yaml::MachineFunction &YamlMF, + PerFunctionMIParsingState &PFS); + + bool parseCalleeSavedRegister(MachineFunction &MF, + PerFunctionMIParsingState &PFS, + std::vector &CSIInfo, + const yaml::StringValue &RegisterSource, + int FrameIdx); + + bool initializeConstantPool(MachineConstantPool &ConstantPool, + const yaml::MachineFunction &YamlMF, + const MachineFunction &MF, + DenseMap &ConstantPoolSlots); + + bool initializeJumpTableInfo(MachineFunction &MF, + const yaml::MachineJumpTable &YamlJTI, + PerFunctionMIParsingState &PFS); private: + bool parseMBBReference(MachineBasicBlock *&MBB, + const yaml::StringValue &Source, MachineFunction &MF, + const PerFunctionMIParsingState &PFS); + /// Return a MIR diagnostic converted from an MI string diagnostic. SMDiagnostic diagFromMIStringDiag(const SMDiagnostic &Error, SMRange SourceRange); @@ -113,6 +141,14 @@ private: /// Create an empty function with the given name. void createDummyFunction(StringRef Name, Module &M); + + void initNames2RegClasses(const MachineFunction &MF); + + /// Check if the given identifier is a name of a register class. + /// + /// Return null if the name isn't a register class. + const TargetRegisterClass *getRegClass(const MachineFunction &MF, + StringRef Name); }; } // end namespace llvm @@ -243,14 +279,22 @@ bool MIRParserImpl::initializeMachineFunction(MachineFunction &MF) { MF.setAlignment(YamlMF.Alignment); MF.setExposesReturnsTwice(YamlMF.ExposesReturnsTwice); MF.setHasInlineAsm(YamlMF.HasInlineAsm); - if (initializeRegisterInfo(MF.getRegInfo(), YamlMF)) + PerFunctionMIParsingState PFS; + if (initializeRegisterInfo(MF, YamlMF, PFS)) return true; + if (!YamlMF.Constants.empty()) { + auto *ConstantPool = MF.getConstantPool(); + assert(ConstantPool && "Constant pool must be created"); + if (initializeConstantPool(*ConstantPool, YamlMF, MF, + PFS.ConstantPoolSlots)) + return true; + } - PerFunctionMIParsingState PFS; const auto &F = *MF.getFunction(); for (const auto &YamlMBB : YamlMF.BasicBlocks) { const BasicBlock *BB = nullptr; const yaml::StringValue &Name = YamlMBB.Name; + const yaml::StringValue &IRBlock = YamlMBB.IRBlock; if (!Name.Value.empty()) { BB = dyn_cast_or_null( F.getValueSymbolTable().lookup(Name.Value)); @@ -260,6 +304,12 @@ bool MIRParserImpl::initializeMachineFunction(MachineFunction &MF) { "' is not defined in the function '" + MF.getName() + "'"); } + if (!IRBlock.Value.empty()) { + // TODO: Report an error when both name and ir block are specified. + SMDiagnostic Error; + if (parseIRBlockReference(BB, SM, MF, IRBlock.Value, PFS, IRSlots, Error)) + return error(Error, IRBlock.SourceRange); + } auto *MBB = MF.CreateMachineBasicBlock(BB); MF.insert(MF.end(), MBB); bool WasInserted = @@ -269,6 +319,18 @@ bool MIRParserImpl::initializeMachineFunction(MachineFunction &MF) { Twine(YamlMBB.ID)); } + if (YamlMF.BasicBlocks.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(MF, YamlMF, PFS)) + 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(MF, YamlMF.JumpTableInfo, PFS)) + return true; // Initialize the machine basic blocks after creating them all so that the // machine instructions parser can resolve the MBB references. unsigned I = 0; @@ -277,6 +339,10 @@ bool MIRParserImpl::initializeMachineFunction(MachineFunction &MF) { PFS)) return true; } + // FIXME: This is a temporary workaround until the reserved registers can be + // serialized. + MF.getRegInfo().freezeReservedRegs(MF); + MF.verify(); return false; } @@ -290,13 +356,32 @@ bool MIRParserImpl::initializeMachineBasicBlock( MBB.setIsLandingPad(YamlMBB.IsLandingPad); SMDiagnostic Error; // Parse the successors. + const auto &Weights = YamlMBB.SuccessorWeights; + bool HasWeights = !Weights.empty(); + if (HasWeights && Weights.size() != YamlMBB.Successors.size()) { + bool IsFew = Weights.size() < YamlMBB.Successors.size(); + return error(IsFew ? Weights.back().SourceRange.End + : Weights[YamlMBB.Successors.size()].SourceRange.Start, + Twine("too ") + (IsFew ? "few" : "many") + + " successor weights, expected " + + Twine(YamlMBB.Successors.size()) + ", have " + + Twine(Weights.size())); + } + size_t SuccessorIndex = 0; for (const auto &MBBSource : YamlMBB.Successors) { MachineBasicBlock *SuccMBB = nullptr; - if (parseMBBReference(SuccMBB, SM, MF, MBBSource.Value, PFS, IRSlots, - Error)) - return error(Error, MBBSource.SourceRange); + if (parseMBBReference(SuccMBB, MBBSource, MF, PFS)) + return true; // TODO: Report an error when adding the same successor more than once. - MBB.addSuccessor(SuccMBB); + MBB.addSuccessor(SuccMBB, HasWeights ? Weights[SuccessorIndex++].Value : 0); + } + // Parse the liveins. + for (const auto &LiveInSource : YamlMBB.LiveIns) { + unsigned Reg = 0; + if (parseNamedRegisterReference(Reg, SM, MF, LiveInSource.Value, PFS, + IRSlots, Error)) + return error(Error, LiveInSource.SourceRange); + MBB.addLiveIn(Reg); } // Parse the instructions. for (const auto &MISource : YamlMBB.Instructions) { @@ -308,8 +393,10 @@ bool MIRParserImpl::initializeMachineBasicBlock( return false; } -bool MIRParserImpl::initializeRegisterInfo( - MachineRegisterInfo &RegInfo, const yaml::MachineFunction &YamlMF) { +bool MIRParserImpl::initializeRegisterInfo(MachineFunction &MF, + const yaml::MachineFunction &YamlMF, + PerFunctionMIParsingState &PFS) { + MachineRegisterInfo &RegInfo = MF.getRegInfo(); assert(RegInfo.isSSA()); if (!YamlMF.IsSSA) RegInfo.leaveSSA(); @@ -317,6 +404,200 @@ bool MIRParserImpl::initializeRegisterInfo( if (!YamlMF.TracksRegLiveness) RegInfo.invalidateLiveness(); RegInfo.enableSubRegLiveness(YamlMF.TracksSubRegLiveness); + + SMDiagnostic Error; + // Parse the virtual register information. + for (const auto &VReg : YamlMF.VirtualRegisters) { + const auto *RC = getRegClass(MF, VReg.Class.Value); + if (!RC) + return error(VReg.Class.SourceRange.Start, + Twine("use of undefined register class '") + + VReg.Class.Value + "'"); + unsigned Reg = RegInfo.createVirtualRegister(RC); + if (!PFS.VirtualRegisterSlots.insert(std::make_pair(VReg.ID.Value, Reg)) + .second) + return error(VReg.ID.SourceRange.Start, + Twine("redefinition of virtual register '%") + + Twine(VReg.ID.Value) + "'"); + if (!VReg.PreferredRegister.Value.empty()) { + unsigned PreferredReg = 0; + if (parseNamedRegisterReference(PreferredReg, SM, MF, + VReg.PreferredRegister.Value, PFS, + IRSlots, Error)) + return error(Error, VReg.PreferredRegister.SourceRange); + RegInfo.setSimpleHint(Reg, PreferredReg); + } + } + + // Parse the liveins. + for (const auto &LiveIn : YamlMF.LiveIns) { + unsigned Reg = 0; + if (parseNamedRegisterReference(Reg, SM, MF, LiveIn.Register.Value, PFS, + IRSlots, Error)) + return error(Error, LiveIn.Register.SourceRange); + unsigned VReg = 0; + if (!LiveIn.VirtualRegister.Value.empty()) { + if (parseVirtualRegisterReference( + VReg, SM, MF, LiveIn.VirtualRegister.Value, PFS, IRSlots, Error)) + return error(Error, LiveIn.VirtualRegister.SourceRange); + } + RegInfo.addLiveIn(Reg, VReg); + } + return false; +} + +bool MIRParserImpl::initializeFrameInfo(MachineFunction &MF, + const yaml::MachineFunction &YamlMF, + PerFunctionMIParsingState &PFS) { + MachineFrameInfo &MFI = *MF.getFrameInfo(); + const Function &F = *MF.getFunction(); + const yaml::MachineFrameInfo &YamlMFI = YamlMF.FrameInfo; + MFI.setFrameAddressIsTaken(YamlMFI.IsFrameAddressTaken); + MFI.setReturnAddressIsTaken(YamlMFI.IsReturnAddressTaken); + MFI.setHasStackMap(YamlMFI.HasStackMap); + MFI.setHasPatchPoint(YamlMFI.HasPatchPoint); + MFI.setStackSize(YamlMFI.StackSize); + MFI.setOffsetAdjustment(YamlMFI.OffsetAdjustment); + if (YamlMFI.MaxAlignment) + MFI.ensureMaxAlignment(YamlMFI.MaxAlignment); + MFI.setAdjustsStack(YamlMFI.AdjustsStack); + MFI.setHasCalls(YamlMFI.HasCalls); + MFI.setMaxCallFrameSize(YamlMFI.MaxCallFrameSize); + MFI.setHasOpaqueSPAdjustment(YamlMFI.HasOpaqueSPAdjustment); + MFI.setHasVAStart(YamlMFI.HasVAStart); + MFI.setHasMustTailInVarArgFunc(YamlMFI.HasMustTailInVarArgFunc); + if (!YamlMFI.SavePoint.Value.empty()) { + MachineBasicBlock *MBB = nullptr; + if (parseMBBReference(MBB, YamlMFI.SavePoint, MF, PFS)) + return true; + MFI.setSavePoint(MBB); + } + if (!YamlMFI.RestorePoint.Value.empty()) { + MachineBasicBlock *MBB = nullptr; + if (parseMBBReference(MBB, YamlMFI.RestorePoint, MF, PFS)) + return true; + MFI.setRestorePoint(MBB); + } + + std::vector CSIInfo; + // Initialize the fixed frame objects. + for (const auto &Object : YamlMF.FixedStackObjects) { + int ObjectIdx; + if (Object.Type != yaml::FixedMachineStackObject::SpillSlot) + ObjectIdx = MFI.CreateFixedObject(Object.Size, Object.Offset, + Object.IsImmutable, Object.IsAliased); + else + ObjectIdx = MFI.CreateFixedSpillStackObject(Object.Size, Object.Offset); + MFI.setObjectAlignment(ObjectIdx, Object.Alignment); + // TODO: Report an error when objects are redefined. + PFS.FixedStackObjectSlots.insert(std::make_pair(Object.ID, ObjectIdx)); + if (parseCalleeSavedRegister(MF, PFS, CSIInfo, Object.CalleeSavedRegister, + ObjectIdx)) + return true; + } + + // Initialize the ordinary frame objects. + for (const auto &Object : YamlMF.StackObjects) { + int ObjectIdx; + const AllocaInst *Alloca = nullptr; + const yaml::StringValue &Name = Object.Name; + if (!Name.Value.empty()) { + Alloca = dyn_cast_or_null( + F.getValueSymbolTable().lookup(Name.Value)); + if (!Alloca) + return error(Name.SourceRange.Start, + "alloca instruction named '" + Name.Value + + "' isn't defined in the function '" + F.getName() + + "'"); + } + if (Object.Type == yaml::MachineStackObject::VariableSized) + ObjectIdx = MFI.CreateVariableSizedObject(Object.Alignment, Alloca); + else + ObjectIdx = MFI.CreateStackObject( + Object.Size, Object.Alignment, + Object.Type == yaml::MachineStackObject::SpillSlot, Alloca); + MFI.setObjectOffset(ObjectIdx, Object.Offset); + // TODO: Report an error when objects are redefined. + PFS.StackObjectSlots.insert(std::make_pair(Object.ID, ObjectIdx)); + if (parseCalleeSavedRegister(MF, PFS, CSIInfo, Object.CalleeSavedRegister, + ObjectIdx)) + return true; + } + MFI.setCalleeSavedInfo(CSIInfo); + if (!CSIInfo.empty()) + MFI.setCalleeSavedInfoValid(true); + return false; +} + +bool MIRParserImpl::parseCalleeSavedRegister( + MachineFunction &MF, PerFunctionMIParsingState &PFS, + std::vector &CSIInfo, + const yaml::StringValue &RegisterSource, int FrameIdx) { + if (RegisterSource.Value.empty()) + return false; + unsigned Reg = 0; + SMDiagnostic Error; + if (parseNamedRegisterReference(Reg, SM, MF, RegisterSource.Value, PFS, + IRSlots, Error)) + return error(Error, RegisterSource.SourceRange); + CSIInfo.push_back(CalleeSavedInfo(Reg, FrameIdx)); + return false; +} + +bool MIRParserImpl::initializeConstantPool( + MachineConstantPool &ConstantPool, const yaml::MachineFunction &YamlMF, + const MachineFunction &MF, + DenseMap &ConstantPoolSlots) { + const auto &M = *MF.getFunction()->getParent(); + SMDiagnostic Error; + for (const auto &YamlConstant : YamlMF.Constants) { + const Constant *Value = dyn_cast_or_null( + parseConstantValue(YamlConstant.Value.Value, Error, M)); + if (!Value) + return error(Error, YamlConstant.Value.SourceRange); + unsigned Alignment = + YamlConstant.Alignment + ? YamlConstant.Alignment + : M.getDataLayout().getPrefTypeAlignment(Value->getType()); + unsigned Index = ConstantPool.getConstantPoolIndex(Value, Alignment); + if (!ConstantPoolSlots.insert(std::make_pair(YamlConstant.ID.Value, Index)) + .second) + return error(YamlConstant.ID.SourceRange.Start, + Twine("redefinition of constant pool item '%const.") + + Twine(YamlConstant.ID.Value) + "'"); + } + return false; +} + +bool MIRParserImpl::initializeJumpTableInfo( + MachineFunction &MF, const yaml::MachineJumpTable &YamlJTI, + PerFunctionMIParsingState &PFS) { + MachineJumpTableInfo *JTI = MF.getOrCreateJumpTableInfo(YamlJTI.Kind); + for (const auto &Entry : YamlJTI.Entries) { + std::vector Blocks; + for (const auto &MBBSource : Entry.Blocks) { + MachineBasicBlock *MBB = nullptr; + if (parseMBBReference(MBB, MBBSource.Value, MF, PFS)) + return true; + Blocks.push_back(MBB); + } + unsigned Index = JTI->createJumpTableIndex(Blocks); + if (!PFS.JumpTableSlots.insert(std::make_pair(Entry.ID.Value, Index)) + .second) + return error(Entry.ID.SourceRange.Start, + Twine("redefinition of jump table entry '%jump-table.") + + Twine(Entry.ID.Value) + "'"); + } + return false; +} + +bool MIRParserImpl::parseMBBReference(MachineBasicBlock *&MBB, + const yaml::StringValue &Source, + MachineFunction &MF, + const PerFunctionMIParsingState &PFS) { + SMDiagnostic Error; + if (llvm::parseMBBReference(MBB, SM, MF, Source.Value, PFS, IRSlots, Error)) + return error(Error, Source.SourceRange); return false; } @@ -367,6 +648,26 @@ SMDiagnostic MIRParserImpl::diagFromLLVMAssemblyDiag(const SMDiagnostic &Error, Error.getFixIts()); } +void MIRParserImpl::initNames2RegClasses(const MachineFunction &MF) { + if (!Names2RegClasses.empty()) + return; + const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo(); + for (unsigned I = 0, E = TRI->getNumRegClasses(); I < E; ++I) { + const auto *RC = TRI->getRegClass(I); + Names2RegClasses.insert( + std::make_pair(StringRef(TRI->getRegClassName(RC)).lower(), RC)); + } +} + +const TargetRegisterClass *MIRParserImpl::getRegClass(const MachineFunction &MF, + StringRef Name) { + initNames2RegClasses(MF); + auto RegClassInfo = Names2RegClasses.find(Name); + if (RegClassInfo == Names2RegClasses.end()) + return nullptr; + return RegClassInfo->getValue(); +} + MIRParser::MIRParser(std::unique_ptr Impl) : Impl(std::move(Impl)) {}