diff options
Diffstat (limited to 'lib')
129 files changed, 2387 insertions, 1657 deletions
diff --git a/lib/Analysis/DebugInfo.cpp b/lib/Analysis/DebugInfo.cpp index 5cfe666..fda69ac 100644 --- a/lib/Analysis/DebugInfo.cpp +++ b/lib/Analysis/DebugInfo.cpp @@ -41,9 +41,9 @@ bool DIDescriptor::ValidDebugInfo(MDNode *N, unsigned OptLevel) { DIDescriptor DI(N); - // Check current version. Allow Version6 for now. + // Check current version. Allow Version7 for now. unsigned Version = DI.getVersion(); - if (Version != LLVMDebugVersion && Version != LLVMDebugVersion6) + if (Version != LLVMDebugVersion && Version != LLVMDebugVersion7) return false; switch (DI.getTag()) { @@ -69,15 +69,6 @@ bool DIDescriptor::ValidDebugInfo(MDNode *N, unsigned OptLevel) { return true; } -DIDescriptor::DIDescriptor(MDNode *N, unsigned RequiredTag) { - DbgNode = N; - - // If this is non-null, check to see if the Tag matches. If not, set to null. - if (N && getTag() != RequiredTag) { - DbgNode = 0; - } -} - StringRef DIDescriptor::getStringField(unsigned Elt) const { if (DbgNode == 0) @@ -132,13 +123,12 @@ unsigned DIVariable::getNumAddrElements() const { /// isBasicType - Return true if the specified tag is legal for /// DIBasicType. bool DIDescriptor::isBasicType() const { - assert(!isNull() && "Invalid descriptor!"); - return getTag() == dwarf::DW_TAG_base_type; + return DbgNode && getTag() == dwarf::DW_TAG_base_type; } /// isDerivedType - Return true if the specified tag is legal for DIDerivedType. bool DIDescriptor::isDerivedType() const { - assert(!isNull() && "Invalid descriptor!"); + if (!DbgNode) return false; switch (getTag()) { case dwarf::DW_TAG_typedef: case dwarf::DW_TAG_pointer_type: @@ -158,7 +148,7 @@ bool DIDescriptor::isDerivedType() const { /// isCompositeType - Return true if the specified tag is legal for /// DICompositeType. bool DIDescriptor::isCompositeType() const { - assert(!isNull() && "Invalid descriptor!"); + if (!DbgNode) return false; switch (getTag()) { case dwarf::DW_TAG_array_type: case dwarf::DW_TAG_structure_type: @@ -175,7 +165,7 @@ bool DIDescriptor::isCompositeType() const { /// isVariable - Return true if the specified tag is legal for DIVariable. bool DIDescriptor::isVariable() const { - assert(!isNull() && "Invalid descriptor!"); + if (!DbgNode) return false; switch (getTag()) { case dwarf::DW_TAG_auto_variable: case dwarf::DW_TAG_arg_variable: @@ -194,15 +184,13 @@ bool DIDescriptor::isType() const { /// isSubprogram - Return true if the specified tag is legal for /// DISubprogram. bool DIDescriptor::isSubprogram() const { - assert(!isNull() && "Invalid descriptor!"); - return getTag() == dwarf::DW_TAG_subprogram; + return DbgNode && getTag() == dwarf::DW_TAG_subprogram; } /// isGlobalVariable - Return true if the specified tag is legal for /// DIGlobalVariable. bool DIDescriptor::isGlobalVariable() const { - assert(!isNull() && "Invalid descriptor!"); - return getTag() == dwarf::DW_TAG_variable; + return DbgNode && getTag() == dwarf::DW_TAG_variable; } /// isGlobal - Return true if the specified tag is legal for DIGlobal. @@ -213,7 +201,7 @@ bool DIDescriptor::isGlobal() const { /// isScope - Return true if the specified tag is one of the scope /// related tag. bool DIDescriptor::isScope() const { - assert(!isNull() && "Invalid descriptor!"); + if (!DbgNode) return false; switch (getTag()) { case dwarf::DW_TAG_compile_unit: case dwarf::DW_TAG_lexical_block: @@ -228,39 +216,39 @@ bool DIDescriptor::isScope() const { /// isCompileUnit - Return true if the specified tag is DW_TAG_compile_unit. bool DIDescriptor::isCompileUnit() const { - assert(!isNull() && "Invalid descriptor!"); - return getTag() == dwarf::DW_TAG_compile_unit; + return DbgNode && getTag() == dwarf::DW_TAG_compile_unit; +} + +/// isFile - Return true if the specified tag is DW_TAG_file_type. +bool DIDescriptor::isFile() const { + return DbgNode && getTag() == dwarf::DW_TAG_file_type; } /// isNameSpace - Return true if the specified tag is DW_TAG_namespace. bool DIDescriptor::isNameSpace() const { - assert(!isNull() && "Invalid descriptor!"); - return getTag() == dwarf::DW_TAG_namespace; + return DbgNode && getTag() == dwarf::DW_TAG_namespace; } /// isLexicalBlock - Return true if the specified tag is DW_TAG_lexical_block. bool DIDescriptor::isLexicalBlock() const { - assert(!isNull() && "Invalid descriptor!"); - return getTag() == dwarf::DW_TAG_lexical_block; + return DbgNode && getTag() == dwarf::DW_TAG_lexical_block; } /// isSubrange - Return true if the specified tag is DW_TAG_subrange_type. bool DIDescriptor::isSubrange() const { - assert(!isNull() && "Invalid descriptor!"); - return getTag() == dwarf::DW_TAG_subrange_type; + return DbgNode && getTag() == dwarf::DW_TAG_subrange_type; } /// isEnumerator - Return true if the specified tag is DW_TAG_enumerator. bool DIDescriptor::isEnumerator() const { - assert(!isNull() && "Invalid descriptor!"); - return getTag() == dwarf::DW_TAG_enumerator; + return DbgNode && getTag() == dwarf::DW_TAG_enumerator; } //===----------------------------------------------------------------------===// // Simple Descriptor Constructors and other Methods //===----------------------------------------------------------------------===// -DIType::DIType(MDNode *N) : DIDescriptor(N) { +DIType::DIType(MDNode *N) : DIScope(N) { if (!N) return; if (!isBasicType() && !isDerivedType() && !isCompositeType()) { DbgNode = 0; @@ -268,7 +256,8 @@ DIType::DIType(MDNode *N) : DIDescriptor(N) { } unsigned DIArray::getNumElements() const { - assert(DbgNode && "Invalid DIArray"); + if (!DbgNode) + return 0; return DbgNode->getNumOperands(); } @@ -276,11 +265,9 @@ unsigned DIArray::getNumElements() const { /// this descriptor. After this completes, the current debug info value /// is erased. void DIDerivedType::replaceAllUsesWith(DIDescriptor &D) { - if (isNull()) + if (!DbgNode) return; - assert(!D.isNull() && "Can not replace with null"); - // Since we use a TrackingVH for the node, its easy for clients to manufacture // legitimate situations where they want to replaceAllUsesWith() on something // which, due to uniquing, has merged with the source. We shield clients from @@ -295,7 +282,7 @@ void DIDerivedType::replaceAllUsesWith(DIDescriptor &D) { /// Verify - Verify that a compile unit is well formed. bool DICompileUnit::Verify() const { - if (isNull()) + if (!DbgNode) return false; StringRef N = getFilename(); if (N.empty()) @@ -306,36 +293,36 @@ bool DICompileUnit::Verify() const { /// Verify - Verify that a type descriptor is well formed. bool DIType::Verify() const { - if (isNull()) + if (!DbgNode) return false; - if (getContext().isNull()) + if (!getContext().Verify()) return false; DICompileUnit CU = getCompileUnit(); - if (!CU.isNull() && !CU.Verify()) + if (!CU.Verify()) return false; return true; } /// Verify - Verify that a composite type descriptor is well formed. bool DICompositeType::Verify() const { - if (isNull()) + if (!DbgNode) return false; - if (getContext().isNull()) + if (!getContext().Verify()) return false; DICompileUnit CU = getCompileUnit(); - if (!CU.isNull() && !CU.Verify()) + if (!CU.Verify()) return false; return true; } /// Verify - Verify that a subprogram descriptor is well formed. bool DISubprogram::Verify() const { - if (isNull()) + if (!DbgNode) return false; - if (getContext().isNull()) + if (!getContext().Verify()) return false; DICompileUnit CU = getCompileUnit(); @@ -343,24 +330,24 @@ bool DISubprogram::Verify() const { return false; DICompositeType Ty = getType(); - if (!Ty.isNull() && !Ty.Verify()) + if (!Ty.Verify()) return false; return true; } /// Verify - Verify that a global variable descriptor is well formed. bool DIGlobalVariable::Verify() const { - if (isNull()) + if (!DbgNode) return false; if (getDisplayName().empty()) return false; - if (getContext().isNull()) + if (!getContext().Verify()) return false; DICompileUnit CU = getCompileUnit(); - if (!CU.isNull() && !CU.Verify()) + if (!CU.Verify()) return false; DIType Ty = getType(); @@ -375,10 +362,10 @@ bool DIGlobalVariable::Verify() const { /// Verify - Verify that a variable descriptor is well formed. bool DIVariable::Verify() const { - if (isNull()) + if (!DbgNode) return false; - if (getContext().isNull()) + if (!getContext().Verify()) return false; DIType Ty = getType(); @@ -388,6 +375,14 @@ bool DIVariable::Verify() const { return true; } +/// Verify - Verify that a location descriptor is well formed. +bool DILocation::Verify() const { + if (!DbgNode) + return false; + + return DbgNode->getNumOperands() == 4; +} + /// getOriginalTypeSize - If this type is derived from a base type then /// return base type size. uint64_t DIDerivedType::getOriginalTypeSize() const { @@ -398,7 +393,7 @@ uint64_t DIDerivedType::getOriginalTypeSize() const { DIType BaseType = getTypeDerivedFrom(); // If this type is not derived from any type then take conservative // approach. - if (BaseType.isNull()) + if (!BaseType.isValid()) return getSizeInBits(); if (BaseType.isDerivedType()) return DIDerivedType(BaseType.getNode()).getOriginalTypeSize(); @@ -422,6 +417,8 @@ bool DISubprogram::describes(const Function *F) { } StringRef DIScope::getFilename() const { + if (!DbgNode) + return StringRef(); if (isLexicalBlock()) return DILexicalBlock(DbgNode).getFilename(); if (isSubprogram()) @@ -430,11 +427,17 @@ StringRef DIScope::getFilename() const { return DICompileUnit(DbgNode).getFilename(); if (isNameSpace()) return DINameSpace(DbgNode).getFilename(); + if (isType()) + return DIType(DbgNode).getFilename(); + if (isFile()) + return DIFile(DbgNode).getFilename(); assert(0 && "Invalid DIScope!"); return StringRef(); } StringRef DIScope::getDirectory() const { + if (!DbgNode) + return StringRef(); if (isLexicalBlock()) return DILexicalBlock(DbgNode).getDirectory(); if (isSubprogram()) @@ -443,6 +446,10 @@ StringRef DIScope::getDirectory() const { return DICompileUnit(DbgNode).getDirectory(); if (isNameSpace()) return DINameSpace(DbgNode).getDirectory(); + if (isType()) + return DIType(DbgNode).getDirectory(); + if (isFile()) + return DIFile(DbgNode).getDirectory(); assert(0 && "Invalid DIScope!"); return StringRef(); } @@ -468,7 +475,7 @@ void DICompileUnit::dump() const { /// dump - Print type. void DIType::dump() const { - if (isNull()) return; + if (!DbgNode) return; StringRef Res = getName(); if (!Res.empty()) @@ -521,8 +528,6 @@ void DIDerivedType::dump() const { /// dump - Print composite type. void DICompositeType::dump() const { DIArray A = getTypeArray(); - if (A.isNull()) - return; dbgs() << " [" << A.getNumElements() << " elements]"; } @@ -665,6 +670,20 @@ DICompileUnit DIFactory::CreateCompileUnit(unsigned LangID, return DICompileUnit(MDNode::get(VMContext, &Elts[0], 10)); } +/// CreateFile - Create a new descriptor for the specified file. +DIFile DIFactory::CreateFile(StringRef Filename, + StringRef Directory, + DICompileUnit CU) { + Value *Elts[] = { + GetTagConstant(dwarf::DW_TAG_file_type), + MDString::get(VMContext, Filename), + MDString::get(VMContext, Directory), + CU.getNode() + }; + + return DIFile(MDNode::get(VMContext, &Elts[0], 4)); +} + /// CreateEnumerator - Create a single enumerator value. DIEnumerator DIFactory::CreateEnumerator(StringRef Name, uint64_t Val){ Value *Elts[] = { @@ -679,7 +698,7 @@ DIEnumerator DIFactory::CreateEnumerator(StringRef Name, uint64_t Val){ /// CreateBasicType - Create a basic type like int, float, etc. DIBasicType DIFactory::CreateBasicType(DIDescriptor Context, StringRef Name, - DICompileUnit CompileUnit, + DIFile F, unsigned LineNumber, uint64_t SizeInBits, uint64_t AlignInBits, @@ -689,7 +708,7 @@ DIBasicType DIFactory::CreateBasicType(DIDescriptor Context, GetTagConstant(dwarf::DW_TAG_base_type), Context.getNode(), MDString::get(VMContext, Name), - CompileUnit.getNode(), + F.getNode(), ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber), ConstantInt::get(Type::getInt64Ty(VMContext), SizeInBits), ConstantInt::get(Type::getInt64Ty(VMContext), AlignInBits), @@ -704,7 +723,7 @@ DIBasicType DIFactory::CreateBasicType(DIDescriptor Context, /// CreateBasicType - Create a basic type like int, float, etc. DIBasicType DIFactory::CreateBasicTypeEx(DIDescriptor Context, StringRef Name, - DICompileUnit CompileUnit, + DIFile F, unsigned LineNumber, Constant *SizeInBits, Constant *AlignInBits, @@ -714,7 +733,7 @@ DIBasicType DIFactory::CreateBasicTypeEx(DIDescriptor Context, GetTagConstant(dwarf::DW_TAG_base_type), Context.getNode(), MDString::get(VMContext, Name), - CompileUnit.getNode(), + F.getNode(), ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber), SizeInBits, AlignInBits, @@ -754,7 +773,7 @@ DIType DIFactory::CreateArtificialType(DIType Ty) { DIDerivedType DIFactory::CreateDerivedType(unsigned Tag, DIDescriptor Context, StringRef Name, - DICompileUnit CompileUnit, + DIFile F, unsigned LineNumber, uint64_t SizeInBits, uint64_t AlignInBits, @@ -765,7 +784,7 @@ DIDerivedType DIFactory::CreateDerivedType(unsigned Tag, GetTagConstant(Tag), Context.getNode(), MDString::get(VMContext, Name), - CompileUnit.getNode(), + F.getNode(), ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber), ConstantInt::get(Type::getInt64Ty(VMContext), SizeInBits), ConstantInt::get(Type::getInt64Ty(VMContext), AlignInBits), @@ -782,7 +801,7 @@ DIDerivedType DIFactory::CreateDerivedType(unsigned Tag, DIDerivedType DIFactory::CreateDerivedTypeEx(unsigned Tag, DIDescriptor Context, StringRef Name, - DICompileUnit CompileUnit, + DIFile F, unsigned LineNumber, Constant *SizeInBits, Constant *AlignInBits, @@ -793,7 +812,7 @@ DIDerivedType DIFactory::CreateDerivedTypeEx(unsigned Tag, GetTagConstant(Tag), Context.getNode(), MDString::get(VMContext, Name), - CompileUnit.getNode(), + F.getNode(), ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber), SizeInBits, AlignInBits, @@ -809,7 +828,7 @@ DIDerivedType DIFactory::CreateDerivedTypeEx(unsigned Tag, DICompositeType DIFactory::CreateCompositeType(unsigned Tag, DIDescriptor Context, StringRef Name, - DICompileUnit CompileUnit, + DIFile F, unsigned LineNumber, uint64_t SizeInBits, uint64_t AlignInBits, @@ -824,7 +843,7 @@ DICompositeType DIFactory::CreateCompositeType(unsigned Tag, GetTagConstant(Tag), Context.getNode(), MDString::get(VMContext, Name), - CompileUnit.getNode(), + F.getNode(), ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber), ConstantInt::get(Type::getInt64Ty(VMContext), SizeInBits), ConstantInt::get(Type::getInt64Ty(VMContext), AlignInBits), @@ -843,7 +862,7 @@ DICompositeType DIFactory::CreateCompositeType(unsigned Tag, DICompositeType DIFactory::CreateCompositeTypeEx(unsigned Tag, DIDescriptor Context, StringRef Name, - DICompileUnit CompileUnit, + DIFile F, unsigned LineNumber, Constant *SizeInBits, Constant *AlignInBits, @@ -857,7 +876,7 @@ DICompositeType DIFactory::CreateCompositeTypeEx(unsigned Tag, GetTagConstant(Tag), Context.getNode(), MDString::get(VMContext, Name), - CompileUnit.getNode(), + F.getNode(), ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber), SizeInBits, AlignInBits, @@ -878,7 +897,7 @@ DISubprogram DIFactory::CreateSubprogram(DIDescriptor Context, StringRef Name, StringRef DisplayName, StringRef LinkageName, - DICompileUnit CompileUnit, + DIFile F, unsigned LineNo, DIType Ty, bool isLocalToUnit, bool isDefinition, @@ -893,7 +912,7 @@ DISubprogram DIFactory::CreateSubprogram(DIDescriptor Context, MDString::get(VMContext, Name), MDString::get(VMContext, DisplayName), MDString::get(VMContext, LinkageName), - CompileUnit.getNode(), + F.getNode(), ConstantInt::get(Type::getInt32Ty(VMContext), LineNo), Ty.getNode(), ConstantInt::get(Type::getInt1Ty(VMContext), isLocalToUnit), @@ -938,7 +957,7 @@ DIGlobalVariable DIFactory::CreateGlobalVariable(DIDescriptor Context, StringRef Name, StringRef DisplayName, StringRef LinkageName, - DICompileUnit CompileUnit, + DIFile F, unsigned LineNo, DIType Ty,bool isLocalToUnit, bool isDefinition, llvm::GlobalVariable *Val) { Value *Elts[] = { @@ -948,7 +967,7 @@ DIFactory::CreateGlobalVariable(DIDescriptor Context, StringRef Name, MDString::get(VMContext, Name), MDString::get(VMContext, DisplayName), MDString::get(VMContext, LinkageName), - CompileUnit.getNode(), + F.getNode(), ConstantInt::get(Type::getInt32Ty(VMContext), LineNo), Ty.getNode(), ConstantInt::get(Type::getInt1Ty(VMContext), isLocalToUnit), @@ -970,13 +989,14 @@ DIFactory::CreateGlobalVariable(DIDescriptor Context, StringRef Name, /// CreateVariable - Create a new descriptor for the specified variable. DIVariable DIFactory::CreateVariable(unsigned Tag, DIDescriptor Context, StringRef Name, - DICompileUnit CompileUnit, unsigned LineNo, + DIFile F, + unsigned LineNo, DIType Ty) { Value *Elts[] = { GetTagConstant(Tag), Context.getNode(), MDString::get(VMContext, Name), - CompileUnit.getNode(), + F.getNode(), ConstantInt::get(Type::getInt32Ty(VMContext), LineNo), Ty.getNode(), }; @@ -988,7 +1008,7 @@ DIVariable DIFactory::CreateVariable(unsigned Tag, DIDescriptor Context, /// which has a complex address expression for its address. DIVariable DIFactory::CreateComplexVariable(unsigned Tag, DIDescriptor Context, const std::string &Name, - DICompileUnit CompileUnit, + DIFile F, unsigned LineNo, DIType Ty, SmallVector<Value *, 9> &addr) { @@ -996,7 +1016,7 @@ DIVariable DIFactory::CreateComplexVariable(unsigned Tag, DIDescriptor Context, Elts.push_back(GetTagConstant(Tag)); Elts.push_back(Context.getNode()); Elts.push_back(MDString::get(VMContext, Name)); - Elts.push_back(CompileUnit.getNode()); + Elts.push_back(F.getNode()); Elts.push_back(ConstantInt::get(Type::getInt32Ty(VMContext), LineNo)); Elts.push_back(Ty.getNode()); Elts.insert(Elts.end(), addr.begin(), addr.end()); @@ -1021,13 +1041,13 @@ DILexicalBlock DIFactory::CreateLexicalBlock(DIDescriptor Context, /// CreateNameSpace - This creates new descriptor for a namespace /// with the specified parent context. DINameSpace DIFactory::CreateNameSpace(DIDescriptor Context, StringRef Name, - DICompileUnit CompileUnit, + DIFile F, unsigned LineNo) { Value *Elts[] = { GetTagConstant(dwarf::DW_TAG_namespace), Context.getNode(), MDString::get(VMContext, Name), - CompileUnit.getNode(), + F.getNode(), ConstantInt::get(Type::getInt32Ty(VMContext), LineNo) }; return DINameSpace(MDNode::get(VMContext, &Elts[0], 5)); @@ -1155,9 +1175,8 @@ void DebugInfoFinder::processModule(Module &M) { /// processLocation - Process DILocation. void DebugInfoFinder::processLocation(DILocation Loc) { - if (Loc.isNull()) return; - DIScope S(Loc.getScope().getNode()); - if (S.isNull()) return; + if (!Loc.Verify()) return; + DIDescriptor S(Loc.getScope().getNode()); if (S.isCompileUnit()) addCompileUnit(DICompileUnit(S.getNode())); else if (S.isSubprogram()) @@ -1177,26 +1196,21 @@ void DebugInfoFinder::processType(DIType DT) { DICompositeType DCT(DT.getNode()); processType(DCT.getTypeDerivedFrom()); DIArray DA = DCT.getTypeArray(); - if (!DA.isNull()) - for (unsigned i = 0, e = DA.getNumElements(); i != e; ++i) { - DIDescriptor D = DA.getElement(i); - DIType TyE = DIType(D.getNode()); - if (!TyE.isNull()) - processType(TyE); - else - processSubprogram(DISubprogram(D.getNode())); - } + for (unsigned i = 0, e = DA.getNumElements(); i != e; ++i) { + DIDescriptor D = DA.getElement(i); + if (D.isType()) + processType(DIType(D.getNode())); + else if (D.isSubprogram()) + processSubprogram(DISubprogram(D.getNode())); + } } else if (DT.isDerivedType()) { DIDerivedType DDT(DT.getNode()); - if (!DDT.isNull()) - processType(DDT.getTypeDerivedFrom()); + processType(DDT.getTypeDerivedFrom()); } } /// processLexicalBlock void DebugInfoFinder::processLexicalBlock(DILexicalBlock LB) { - if (LB.isNull()) - return; DIScope Context = LB.getContext(); if (Context.isLexicalBlock()) return processLexicalBlock(DILexicalBlock(Context.getNode())); @@ -1206,8 +1220,6 @@ void DebugInfoFinder::processLexicalBlock(DILexicalBlock LB) { /// processSubprogram - Process DISubprogram. void DebugInfoFinder::processSubprogram(DISubprogram SP) { - if (SP.isNull()) - return; if (!addSubprogram(SP)) return; addCompileUnit(SP.getCompileUnit()); @@ -1216,20 +1228,23 @@ void DebugInfoFinder::processSubprogram(DISubprogram SP) { /// processDeclare - Process DbgDeclareInst. void DebugInfoFinder::processDeclare(DbgDeclareInst *DDI) { - DIVariable DV(cast<MDNode>(DDI->getVariable())); - if (DV.isNull()) + MDNode *N = dyn_cast<MDNode>(DDI->getVariable()); + if (!N) return; + + DIDescriptor DV(N); + if (!DV.isVariable()) return; if (!NodesSeen.insert(DV.getNode())) return; - addCompileUnit(DV.getCompileUnit()); - processType(DV.getType()); + addCompileUnit(DIVariable(N).getCompileUnit()); + processType(DIVariable(N).getType()); } /// addType - Add type into Tys. bool DebugInfoFinder::addType(DIType DT) { - if (DT.isNull()) + if (!DT.isValid()) return false; if (!NodesSeen.insert(DT.getNode())) @@ -1241,7 +1256,7 @@ bool DebugInfoFinder::addType(DIType DT) { /// addCompileUnit - Add compile unit into CUs. bool DebugInfoFinder::addCompileUnit(DICompileUnit CU) { - if (CU.isNull()) + if (!CU.Verify()) return false; if (!NodesSeen.insert(CU.getNode())) @@ -1253,7 +1268,7 @@ bool DebugInfoFinder::addCompileUnit(DICompileUnit CU) { /// addGlobalVariable - Add global variable into GVs. bool DebugInfoFinder::addGlobalVariable(DIGlobalVariable DIG) { - if (DIG.isNull()) + if (!DIDescriptor(DIG.getNode()).isGlobalVariable()) return false; if (!NodesSeen.insert(DIG.getNode())) @@ -1265,7 +1280,7 @@ bool DebugInfoFinder::addGlobalVariable(DIGlobalVariable DIG) { // addSubprogram - Add subprgoram into SPs. bool DebugInfoFinder::addSubprogram(DISubprogram SP) { - if (SP.isNull()) + if (!DIDescriptor(SP.getNode()).isSubprogram()) return false; if (!NodesSeen.insert(SP.getNode())) @@ -1283,10 +1298,10 @@ static Value *findDbgGlobalDeclare(GlobalVariable *V) { return 0; for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) { - DIGlobalVariable DIG(cast_or_null<MDNode>(NMD->getOperand(i))); - if (DIG.isNull()) + DIDescriptor DIG(cast_or_null<MDNode>(NMD->getOperand(i))); + if (!DIG.isGlobalVariable()) continue; - if (DIG.getGlobal() == V) + if (DIGlobalVariable(DIG.getNode()).getGlobal() == V) return DIG.getNode(); } return 0; @@ -1378,12 +1393,6 @@ DebugLoc llvm::ExtractDebugLocation(DILocation &Loc, /// getDISubprogram - Find subprogram that is enclosing this scope. DISubprogram llvm::getDISubprogram(MDNode *Scope) { DIDescriptor D(Scope); - if (D.isNull()) - return DISubprogram(); - - if (D.isCompileUnit()) - return DISubprogram(); - if (D.isSubprogram()) return DISubprogram(Scope); @@ -1395,9 +1404,6 @@ DISubprogram llvm::getDISubprogram(MDNode *Scope) { /// getDICompositeType - Find underlying composite type. DICompositeType llvm::getDICompositeType(DIType T) { - if (T.isNull()) - return DICompositeType(); - if (T.isCompositeType()) return DICompositeType(T.getNode()); diff --git a/lib/Analysis/InlineCost.cpp b/lib/Analysis/InlineCost.cpp index ca50a17..0f1f93b 100644 --- a/lib/Analysis/InlineCost.cpp +++ b/lib/Analysis/InlineCost.cpp @@ -352,11 +352,6 @@ InlineCost InlineCostAnalyzer::getInlineCost(CallSite CS, // Calls usually take a long time, so they make the inlining gain smaller. InlineCost += CalleeFI.Metrics.NumCalls * InlineConstants::CallPenalty; - // Don't inline into something too big, which would make it bigger. - // "size" here is the number of basic blocks, not instructions. - // - InlineCost += Caller->size()/15; - // Look at the size of the callee. Each instruction counts as 5. InlineCost += CalleeFI.Metrics.NumInsts*InlineConstants::InstrCost; @@ -388,3 +383,45 @@ float InlineCostAnalyzer::getInlineFudgeFactor(CallSite CS) { Factor += 1.5f; return Factor; } + +/// growCachedCostInfo - update the cached cost info for Caller after Callee has +/// been inlined. +void +InlineCostAnalyzer::growCachedCostInfo(Function* Caller, Function* Callee) { + FunctionInfo &CallerFI = CachedFunctionInfo[Caller]; + + // For small functions we prefer to recalculate the cost for better accuracy. + if (CallerFI.Metrics.NumBlocks < 10 || CallerFI.Metrics.NumInsts < 1000) { + resetCachedCostInfo(Caller); + return; + } + + // For large functions, we can save a lot of computation time by skipping + // recalculations. + if (CallerFI.Metrics.NumCalls > 0) + --CallerFI.Metrics.NumCalls; + + if (Callee) { + FunctionInfo &CalleeFI = CachedFunctionInfo[Callee]; + if (!CalleeFI.Metrics.NumBlocks) { + resetCachedCostInfo(Caller); + return; + } + CallerFI.Metrics.NeverInline |= CalleeFI.Metrics.NeverInline; + CallerFI.Metrics.usesDynamicAlloca |= CalleeFI.Metrics.usesDynamicAlloca; + + CallerFI.Metrics.NumInsts += CalleeFI.Metrics.NumInsts; + CallerFI.Metrics.NumBlocks += CalleeFI.Metrics.NumBlocks; + CallerFI.Metrics.NumCalls += CalleeFI.Metrics.NumCalls; + CallerFI.Metrics.NumVectorInsts += CalleeFI.Metrics.NumVectorInsts; + CallerFI.Metrics.NumRets += CalleeFI.Metrics.NumRets; + + // analyzeBasicBlock counts each function argument as an inst. + if (CallerFI.Metrics.NumInsts >= Callee->arg_size()) + CallerFI.Metrics.NumInsts -= Callee->arg_size(); + else + CallerFI.Metrics.NumInsts = 0; + } + // We are not updating the argumentweights. We have already determined that + // Caller is a fairly large function, so we accept the loss of precision. +} diff --git a/lib/Analysis/LoopInfo.cpp b/lib/Analysis/LoopInfo.cpp index 453af5a..2139c29 100644 --- a/lib/Analysis/LoopInfo.cpp +++ b/lib/Analysis/LoopInfo.cpp @@ -264,6 +264,13 @@ unsigned Loop::getSmallConstantTripMultiple() const { /// isLCSSAForm - Return true if the Loop is in LCSSA form bool Loop::isLCSSAForm() const { + // Collect all the reachable blocks in the function, for fast lookups. + SmallPtrSet<BasicBlock *, 32> ReachableBBs; + BasicBlock *EntryBB = getHeader()->getParent()->begin(); + for (df_iterator<BasicBlock *> NI = df_begin(EntryBB), + NE = df_end(EntryBB); NI != NE; ++NI) + ReachableBBs.insert(*NI); + // Sort the blocks vector so that we can use binary search to do quick // lookups. SmallPtrSet<BasicBlock *, 16> LoopBBs(block_begin(), block_end()); @@ -277,9 +284,13 @@ bool Loop::isLCSSAForm() const { if (PHINode *P = dyn_cast<PHINode>(*UI)) UserBB = P->getIncomingBlock(UI); - // Check the current block, as a fast-path. Most values are used in - // the same block they are defined in. - if (UserBB != BB && !LoopBBs.count(UserBB)) + // Check the current block, as a fast-path, before checking whether + // the use is anywhere in the loop. Most values are used in the same + // block they are defined in. Also, blocks not reachable from the + // entry are special; uses in them don't need to go through PHIs. + if (UserBB != BB && + !LoopBBs.count(UserBB) && + ReachableBBs.count(UserBB)) return false; } } diff --git a/lib/Analysis/ScalarEvolution.cpp b/lib/Analysis/ScalarEvolution.cpp index b979f33..15f072d 100644 --- a/lib/Analysis/ScalarEvolution.cpp +++ b/lib/Analysis/ScalarEvolution.cpp @@ -3101,9 +3101,16 @@ const SCEV *ScalarEvolution::createSCEV(Value *V) { return getUnknown(V); unsigned Opcode = Instruction::UserOp1; - if (Instruction *I = dyn_cast<Instruction>(V)) + if (Instruction *I = dyn_cast<Instruction>(V)) { Opcode = I->getOpcode(); - else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V)) + + // Don't attempt to analyze instructions in blocks that aren't + // reachable. Such instructions don't matter, and they aren't required + // to obey basic rules for definitions dominating uses which this + // analysis depends on. + if (!DT->isReachableFromEntry(I->getParent())) + return getUnknown(V); + } else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V)) Opcode = CE->getOpcode(); else if (ConstantInt *CI = dyn_cast<ConstantInt>(V)) return getConstant(CI); diff --git a/lib/Analysis/ScalarEvolutionExpander.cpp b/lib/Analysis/ScalarEvolutionExpander.cpp index e27da96..3c2cbfb 100644 --- a/lib/Analysis/ScalarEvolutionExpander.cpp +++ b/lib/Analysis/ScalarEvolutionExpander.cpp @@ -1286,6 +1286,8 @@ Value *SCEVExpander::expand(const SCEV *S) { // there) so that it is guaranteed to dominate any user inside the loop. if (L && S->hasComputableLoopEvolution(L) && L != PostIncLoop) InsertPt = L->getHeader()->getFirstNonPHI(); + while (isa<DbgInfoIntrinsic>(InsertPt)) + InsertPt = llvm::next(BasicBlock::iterator(InsertPt)); while (isInsertedInstruction(InsertPt)) InsertPt = llvm::next(BasicBlock::iterator(InsertPt)); break; diff --git a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index bd2b1b6..4978fba 100644 --- a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -61,7 +61,7 @@ AsmPrinter::AsmPrinter(formatted_raw_ostream &o, TargetMachine &tm, : MachineFunctionPass(&ID), O(o), TM(tm), MAI(T), TRI(tm.getRegisterInfo()), OutContext(Ctx), OutStreamer(Streamer), - LastMI(0), LastFn(0), Counter(~0U), PrevDLT(NULL) { + LastMI(0), LastFn(0), Counter(~0U), SetCounter(0), PrevDLT(NULL) { DW = 0; MMI = 0; VerboseAsm = Streamer.isVerboseAsm(); } @@ -335,7 +335,7 @@ static void EmitComments(const MachineInstr &MI, raw_ostream &CommentOS) { // Print source line info. DIScope Scope = DLT.getScope(); // Omit the directory, because it's likely to be long and uninteresting. - if (!Scope.isNull()) + if (Scope.Verify()) CommentOS << Scope.getFilename(); else CommentOS << "<unknown>"; @@ -893,6 +893,31 @@ void AsmPrinter::EmitInt64(uint64_t Value) const { OutStreamer.EmitIntValue(Value, 8, 0/*addrspace*/); } +/// EmitLabelDifference - Emit something like ".long Hi-Lo" where the size +/// in bytes of the directive is specified by Size and Hi/Lo specify the +/// labels. This implicitly uses .set if it is available. +void AsmPrinter::EmitLabelDifference(const MCSymbol *Hi, const MCSymbol *Lo, + unsigned Size) const { + // Get the Hi-Lo expression. + const MCExpr *Diff = + MCBinaryExpr::CreateSub(MCSymbolRefExpr::Create(Hi, OutContext), + MCSymbolRefExpr::Create(Lo, OutContext), + OutContext); + + if (!MAI->hasSetDirective()) { + OutStreamer.EmitValue(Diff, Size, 0/*AddrSpace*/); + return; + } + + // Otherwise, emit with .set (aka assignment). + MCSymbol *SetLabel = + OutContext.GetOrCreateTemporarySymbol(Twine(MAI->getPrivateGlobalPrefix()) + + "set" + Twine(SetCounter++)); + OutStreamer.EmitAssignment(SetLabel, Diff); + OutStreamer.EmitSymbolValue(SetLabel, Size, 0/*AddrSpace*/); +} + + //===----------------------------------------------------------------------===// // EmitAlignment - Emit an alignment directive to the specified power of @@ -1287,18 +1312,16 @@ void AsmPrinter::processDebugLoc(const MachineInstr *MI, if (DL.isUnknown()) return; DILocation CurDLT = MF->getDILocation(DL); - if (CurDLT.getScope().isNull()) + if (!CurDLT.getScope().Verify()) return; if (!BeforePrintingInsn) { // After printing instruction DW->EndScope(MI); } else if (CurDLT.getNode() != PrevDLT) { - unsigned L = DW->RecordSourceLine(CurDLT.getLineNumber(), - CurDLT.getColumnNumber(), - CurDLT.getScope().getNode()); - printLabel(L); - O << '\n'; + MCSymbol *L = DW->RecordSourceLine(CurDLT.getLineNumber(), + CurDLT.getColumnNumber(), + CurDLT.getScope().getNode()); DW->BeginScope(MI, L); PrevDLT = CurDLT.getNode(); } @@ -1529,12 +1552,17 @@ void AsmPrinter::printKill(const MachineInstr *MI) const { /// printLabel - This method prints a local label used by debug and /// exception handling tables. void AsmPrinter::printLabelInst(const MachineInstr *MI) const { - printLabel(MI->getOperand(0).getImm()); - OutStreamer.AddBlankLine(); + MCSymbol *Sym = + OutContext.GetOrCreateTemporarySymbol(Twine(MAI->getPrivateGlobalPrefix()) + + "label" + Twine(MI->getOperand(0).getImm())); + OutStreamer.EmitLabel(Sym); } void AsmPrinter::printLabel(unsigned Id) const { - O << MAI->getPrivateGlobalPrefix() << "label" << Id << ':'; + MCSymbol *Sym = + OutContext.GetOrCreateTemporarySymbol(Twine(MAI->getPrivateGlobalPrefix()) + + "label" + Twine(Id)); + OutStreamer.EmitLabel(Sym); } /// PrintAsmOperand - Print the specified operand of MI, an INLINEASM @@ -1575,15 +1603,14 @@ MCSymbol *AsmPrinter::GetBlockAddressSymbol(const Function *F, "_" + FnName.str() + "_" + BB->getName(), Mangler::Private); - return OutContext.GetOrCreateSymbol(NameResult.str()); + return OutContext.GetOrCreateTemporarySymbol(NameResult.str()); } /// GetCPISymbol - Return the symbol for the specified constant pool entry. MCSymbol *AsmPrinter::GetCPISymbol(unsigned CPID) const { - SmallString<60> Name; - raw_svector_ostream(Name) << MAI->getPrivateGlobalPrefix() << "CPI" - << getFunctionNumber() << '_' << CPID; - return OutContext.GetOrCreateSymbol(Name.str()); + return OutContext.GetOrCreateTemporarySymbol + (Twine(MAI->getPrivateGlobalPrefix()) + "CPI" + Twine(getFunctionNumber()) + + "_" + Twine(CPID)); } /// GetJTISymbol - Return the symbol for the specified jump table entry. @@ -1594,10 +1621,9 @@ MCSymbol *AsmPrinter::GetJTISymbol(unsigned JTID, bool isLinkerPrivate) const { /// GetJTSetSymbol - Return the symbol for the specified jump table .set /// FIXME: privatize to AsmPrinter. MCSymbol *AsmPrinter::GetJTSetSymbol(unsigned UID, unsigned MBBID) const { - SmallString<60> Name; - raw_svector_ostream(Name) << MAI->getPrivateGlobalPrefix() - << getFunctionNumber() << '_' << UID << "_set_" << MBBID; - return OutContext.GetOrCreateSymbol(Name.str()); + return OutContext.GetOrCreateTemporarySymbol + (Twine(MAI->getPrivateGlobalPrefix()) + Twine(getFunctionNumber()) + "_" + + Twine(UID) + "_set_" + Twine(MBBID)); } /// GetGlobalValueSymbol - Return the MCSymbol for the specified global @@ -1605,7 +1631,10 @@ MCSymbol *AsmPrinter::GetJTSetSymbol(unsigned UID, unsigned MBBID) const { MCSymbol *AsmPrinter::GetGlobalValueSymbol(const GlobalValue *GV) const { SmallString<60> NameStr; Mang->getNameWithPrefix(NameStr, GV, false); - return OutContext.GetOrCreateSymbol(NameStr.str()); + + if (!GV->hasPrivateLinkage()) + return OutContext.GetOrCreateSymbol(NameStr.str()); + return OutContext.GetOrCreateTemporarySymbol(NameStr.str()); } /// GetSymbolWithGlobalValueBase - Return the MCSymbol for a symbol with @@ -1617,7 +1646,9 @@ MCSymbol *AsmPrinter::GetSymbolWithGlobalValueBase(const GlobalValue *GV, SmallString<60> NameStr; Mang->getNameWithPrefix(NameStr, GV, ForcePrivate); NameStr.append(Suffix.begin(), Suffix.end()); - return OutContext.GetOrCreateSymbol(NameStr.str()); + if (!GV->hasPrivateLinkage() && !ForcePrivate) + return OutContext.GetOrCreateSymbol(NameStr.str()); + return OutContext.GetOrCreateTemporarySymbol(NameStr.str()); } /// GetExternalSymbolSymbol - Return the MCSymbol for the specified diff --git a/lib/CodeGen/AsmPrinter/CMakeLists.txt b/lib/CodeGen/AsmPrinter/CMakeLists.txt index 066aaab..7dc1fb5 100644 --- a/lib/CodeGen/AsmPrinter/CMakeLists.txt +++ b/lib/CodeGen/AsmPrinter/CMakeLists.txt @@ -3,7 +3,6 @@ add_llvm_library(LLVMAsmPrinter DIE.cpp DwarfDebug.cpp DwarfException.cpp - DwarfLabel.cpp DwarfPrinter.cpp DwarfWriter.cpp OcamlGCPrinter.cpp diff --git a/lib/CodeGen/AsmPrinter/DIE.cpp b/lib/CodeGen/AsmPrinter/DIE.cpp index 63360c0..e97754e 100644 --- a/lib/CodeGen/AsmPrinter/DIE.cpp +++ b/lib/CodeGen/AsmPrinter/DIE.cpp @@ -131,17 +131,15 @@ void DIE::print(raw_ostream &O, unsigned IncIndent) { << "Die: " << format("0x%lx", (long)(intptr_t)this) << ", Offset: " << Offset - << ", Size: " << Size - << "\n"; + << ", Size: " << Size << "\n"; O << Indent << dwarf::TagString(Abbrev.getTag()) << " " - << dwarf::ChildrenString(Abbrev.getChildrenFlag()); + << dwarf::ChildrenString(Abbrev.getChildrenFlag()) << "\n"; } else { - O << "Size: " << Size; + O << "Size: " << Size << "\n"; } - O << "\n"; const SmallVector<DIEAbbrevData, 8> &Data = Abbrev.getData(); @@ -254,51 +252,27 @@ void DIEString::print(raw_ostream &O) { #endif //===----------------------------------------------------------------------===// -// DIEDwarfLabel Implementation +// DIELabel Implementation //===----------------------------------------------------------------------===// /// EmitValue - Emit label value. /// -void DIEDwarfLabel::EmitValue(DwarfPrinter *D, unsigned Form) const { +void DIELabel::EmitValue(DwarfPrinter *D, unsigned Form) const { bool IsSmall = Form == dwarf::DW_FORM_data4; - D->EmitReference(Label, false, IsSmall); + unsigned Size = IsSmall ? 4 : D->getTargetData()->getPointerSize(); + D->getAsm()->OutStreamer.EmitSymbolValue(Label, Size, 0/*AddrSpace*/); } /// SizeOf - Determine size of label value in bytes. /// -unsigned DIEDwarfLabel::SizeOf(const TargetData *TD, unsigned Form) const { +unsigned DIELabel::SizeOf(const TargetData *TD, unsigned Form) const { if (Form == dwarf::DW_FORM_data4) return 4; return TD->getPointerSize(); } #ifndef NDEBUG -void DIEDwarfLabel::print(raw_ostream &O) { - O << "Lbl: "; - Label.print(O); -} -#endif - -//===----------------------------------------------------------------------===// -// DIEObjectLabel Implementation -//===----------------------------------------------------------------------===// - -/// EmitValue - Emit label value. -/// -void DIEObjectLabel::EmitValue(DwarfPrinter *D, unsigned Form) const { - bool IsSmall = Form == dwarf::DW_FORM_data4; - D->EmitReference(Sym, false, IsSmall); -} - -/// SizeOf - Determine size of label value in bytes. -/// -unsigned DIEObjectLabel::SizeOf(const TargetData *TD, unsigned Form) const { - if (Form == dwarf::DW_FORM_data4) return 4; - return TD->getPointerSize(); -} - -#ifndef NDEBUG -void DIEObjectLabel::print(raw_ostream &O) { - O << "Obj: " << Sym->getName(); +void DIELabel::print(raw_ostream &O) { + O << "Lbl: " << Label->getName(); } #endif @@ -310,10 +284,7 @@ void DIEObjectLabel::print(raw_ostream &O) { /// void DIESectionOffset::EmitValue(DwarfPrinter *D, unsigned Form) const { bool IsSmall = Form == dwarf::DW_FORM_data4; - D->EmitSectionOffset(Label.getTag(), Section.getTag(), - Label.getNumber(), Section.getNumber(), - IsSmall, IsEH, UseSet); - D->getAsm()->O << '\n'; // FIXME: Necesssary? + D->EmitSectionOffset(Label, Section, IsSmall, IsEH); } /// SizeOf - Determine size of delta value in bytes. @@ -325,11 +296,8 @@ unsigned DIESectionOffset::SizeOf(const TargetData *TD, unsigned Form) const { #ifndef NDEBUG void DIESectionOffset::print(raw_ostream &O) { - O << "Off: "; - Label.print(O); - O << "-"; - Section.print(O); - O << "-" << IsEH << "-" << UseSet; + O << "Off: " << Label->getName() << "-" << Section->getName() + << "-" << IsEH; } #endif @@ -353,10 +321,7 @@ unsigned DIEDelta::SizeOf(const TargetData *TD, unsigned Form) const { #ifndef NDEBUG void DIEDelta::print(raw_ostream &O) { - O << "Del: "; - LabelHi.print(O); - O << "-"; - LabelLo.print(O); + O << "Del: " << LabelHi->getName() << "-" << LabelLo->getName(); } #endif @@ -400,15 +365,13 @@ void DIEBlock::EmitValue(DwarfPrinter *D, unsigned Form) const { case dwarf::DW_FORM_block1: Asm->EmitInt8(Size); break; case dwarf::DW_FORM_block2: Asm->EmitInt16(Size); break; case dwarf::DW_FORM_block4: Asm->EmitInt32(Size); break; - case dwarf::DW_FORM_block: D->EmitULEB128(Size); break; - default: llvm_unreachable("Improper form for block"); break; + case dwarf::DW_FORM_block: D->EmitULEB128(Size); break; + default: llvm_unreachable("Improper form for block"); break; } const SmallVector<DIEAbbrevData, 8> &AbbrevData = Abbrev.getData(); - for (unsigned i = 0, N = Values.size(); i < N; ++i) { - Asm->O << '\n'; + for (unsigned i = 0, N = Values.size(); i < N; ++i) Values[i]->EmitValue(D, AbbrevData[i].getForm()); - } } /// SizeOf - Determine size of block data in bytes. diff --git a/lib/CodeGen/AsmPrinter/DIE.h b/lib/CodeGen/AsmPrinter/DIE.h index af90289..e08d748 100644 --- a/lib/CodeGen/AsmPrinter/DIE.h +++ b/lib/CodeGen/AsmPrinter/DIE.h @@ -14,7 +14,6 @@ #ifndef CODEGEN_ASMPRINTER_DIE_H__ #define CODEGEN_ASMPRINTER_DIE_H__ -#include "DwarfLabel.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Support/Compiler.h" @@ -26,6 +25,7 @@ namespace llvm { class DwarfPrinter; class TargetData; class MCSymbol; + class raw_ostream; //===--------------------------------------------------------------------===// /// DIEAbbrevData - Dwarf abbreviation data, describes the one attribute of a @@ -203,7 +203,6 @@ namespace llvm { isInteger, isString, isLabel, - isAsIsLabel, isSectionOffset, isDelta, isEntry, @@ -306,12 +305,12 @@ namespace llvm { }; //===--------------------------------------------------------------------===// - /// DIEDwarfLabel - A Dwarf internal label expression DIE. + /// DIELabel - A label expression DIE. // - class DIEDwarfLabel : public DIEValue { - const DWLabel Label; + class DIELabel : public DIEValue { + const MCSymbol *Label; public: - explicit DIEDwarfLabel(const DWLabel &L) : DIEValue(isLabel), Label(L) {} + explicit DIELabel(const MCSymbol *L) : DIEValue(isLabel), Label(L) {} /// EmitValue - Emit label value. /// @@ -322,7 +321,7 @@ namespace llvm { virtual unsigned SizeOf(const TargetData *TD, unsigned Form) const; // Implement isa/cast/dyncast. - static bool classof(const DIEDwarfLabel *) { return true; } + static bool classof(const DIELabel *) { return true; } static bool classof(const DIEValue *L) { return L->getType() == isLabel; } #ifndef NDEBUG @@ -331,46 +330,17 @@ namespace llvm { }; //===--------------------------------------------------------------------===// - /// DIEObjectLabel - A label to an object in code or data. - // - class DIEObjectLabel : public DIEValue { - const MCSymbol *Sym; - public: - explicit DIEObjectLabel(const MCSymbol *S) - : DIEValue(isAsIsLabel), Sym(S) {} - - /// EmitValue - Emit label value. - /// - virtual void EmitValue(DwarfPrinter *D, unsigned Form) const; - - /// SizeOf - Determine size of label value in bytes. - /// - virtual unsigned SizeOf(const TargetData *TD, unsigned Form) const; - - // Implement isa/cast/dyncast. - static bool classof(const DIEObjectLabel *) { return true; } - static bool classof(const DIEValue *L) { - return L->getType() == isAsIsLabel; - } - -#ifndef NDEBUG - virtual void print(raw_ostream &O); -#endif - }; - - //===--------------------------------------------------------------------===// /// DIESectionOffset - A section offset DIE. /// class DIESectionOffset : public DIEValue { - const DWLabel Label; - const DWLabel Section; + const MCSymbol *Label; + const MCSymbol *Section; bool IsEH : 1; - bool UseSet : 1; public: - DIESectionOffset(const DWLabel &Lab, const DWLabel &Sec, - bool isEH = false, bool useSet = true) + DIESectionOffset(const MCSymbol *Lab, const MCSymbol *Sec, + bool isEH = false) : DIEValue(isSectionOffset), Label(Lab), Section(Sec), - IsEH(isEH), UseSet(useSet) {} + IsEH(isEH) {} /// EmitValue - Emit section offset. /// @@ -395,10 +365,10 @@ namespace llvm { /// DIEDelta - A simple label difference DIE. /// class DIEDelta : public DIEValue { - const DWLabel LabelHi; - const DWLabel LabelLo; + const MCSymbol *LabelHi; + const MCSymbol *LabelLo; public: - DIEDelta(const DWLabel &Hi, const DWLabel &Lo) + DIEDelta(const MCSymbol *Hi, const MCSymbol *Lo) : DIEValue(isDelta), LabelHi(Hi), LabelLo(Lo) {} /// EmitValue - Emit delta value. diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp index 5ad1e5e..36be5b9 100644 --- a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -10,14 +10,16 @@ // This file contains support for writing dwarf debug info into asm files. // //===----------------------------------------------------------------------===// + #define DEBUG_TYPE "dwarfdebug" #include "DwarfDebug.h" #include "llvm/Module.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCSection.h" #include "llvm/MC/MCStreamer.h" -#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCSymbol.h" #include "llvm/Target/Mangler.h" #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetFrameInfo.h" @@ -170,8 +172,8 @@ class DbgScope { // Location at which this scope is inlined. AssertingVH<MDNode> InlinedAtLocation; bool AbstractScope; // Abstract Scope - unsigned StartLabelID; // Label ID of the beginning of scope. - unsigned EndLabelID; // Label ID of the end of scope. + MCSymbol *StartLabel; // Label ID of the beginning of scope. + MCSymbol *EndLabel; // Label ID of the end of scope. const MachineInstr *LastInsn; // Last instruction of this scope. const MachineInstr *FirstInsn; // First instruction of this scope. SmallVector<DbgScope *, 4> Scopes; // Scopes defined in scope. @@ -182,7 +184,7 @@ class DbgScope { public: DbgScope(DbgScope *P, DIDescriptor D, MDNode *I = 0) : Parent(P), Desc(D), InlinedAtLocation(I), AbstractScope(false), - StartLabelID(0), EndLabelID(0), + StartLabel(0), EndLabel(0), LastInsn(0), FirstInsn(0), IndentLevel(0) {} virtual ~DbgScope(); @@ -194,12 +196,12 @@ public: return InlinedAtLocation; } MDNode *getScopeNode() const { return Desc.getNode(); } - unsigned getStartLabelID() const { return StartLabelID; } - unsigned getEndLabelID() const { return EndLabelID; } + MCSymbol *getStartLabel() const { return StartLabel; } + MCSymbol *getEndLabel() const { return EndLabel; } SmallVector<DbgScope *, 4> &getScopes() { return Scopes; } SmallVector<DbgVariable *, 8> &getVariables() { return Variables; } - void setStartLabelID(unsigned S) { StartLabelID = S; } - void setEndLabelID(unsigned E) { EndLabelID = E; } + void setStartLabel(MCSymbol *S) { StartLabel = S; } + void setEndLabel(MCSymbol *E) { EndLabel = E; } void setLastInsn(const MachineInstr *MI) { LastInsn = MI; } const MachineInstr *getLastInsn() { return LastInsn; } void setFirstInsn(const MachineInstr *MI) { FirstInsn = MI; } @@ -263,7 +265,7 @@ void DbgScope::dump() const { err.indent(IndentLevel); MDNode *N = Desc.getNode(); N->dump(); - err << " [" << StartLabelID << ", " << EndLabelID << "]\n"; + err << " [" << StartLabel << ", " << EndLabel << "]\n"; if (AbstractScope) err << "Abstract Scope\n"; @@ -288,7 +290,7 @@ DbgScope::~DbgScope() { } // end llvm namespace DwarfDebug::DwarfDebug(raw_ostream &OS, AsmPrinter *A, const MCAsmInfo *T) - : DwarfPrinter(OS, A, T, "dbg"), ModuleCU(0), + : DwarfPrinter(OS, A, T), ModuleCU(0), AbbreviationsSet(InitAbbreviationsSetSize), Abbreviations(), DIEValues(), StringPool(), SectionSourceLines(), didInitial(false), shouldEmit(false), @@ -366,17 +368,8 @@ void DwarfDebug::addString(DIE *Die, unsigned Attribute, unsigned Form, /// addLabel - Add a Dwarf label attribute data and value. /// void DwarfDebug::addLabel(DIE *Die, unsigned Attribute, unsigned Form, - const DWLabel &Label) { - DIEValue *Value = new DIEDwarfLabel(Label); - DIEValues.push_back(Value); - Die->addValue(Attribute, Form, Value); -} - -/// addObjectLabel - Add an non-Dwarf label attribute data and value. -/// -void DwarfDebug::addObjectLabel(DIE *Die, unsigned Attribute, unsigned Form, - const MCSymbol *Sym) { - DIEValue *Value = new DIEObjectLabel(Sym); + const MCSymbol *Label) { + DIEValue *Value = new DIELabel(Label); DIEValues.push_back(Value); Die->addValue(Attribute, Form, Value); } @@ -384,9 +377,9 @@ void DwarfDebug::addObjectLabel(DIE *Die, unsigned Attribute, unsigned Form, /// addSectionOffset - Add a section offset label attribute data and value. /// void DwarfDebug::addSectionOffset(DIE *Die, unsigned Attribute, unsigned Form, - const DWLabel &Label, const DWLabel &Section, - bool isEH, bool useSet) { - DIEValue *Value = new DIESectionOffset(Label, Section, isEH, useSet); + const MCSymbol *Label,const MCSymbol *Section, + bool isEH) { + DIEValue *Value = new DIESectionOffset(Label, Section, isEH); DIEValues.push_back(Value); Die->addValue(Attribute, Form, Value); } @@ -394,7 +387,7 @@ void DwarfDebug::addSectionOffset(DIE *Die, unsigned Attribute, unsigned Form, /// addDelta - Add a label delta attribute data and value. /// void DwarfDebug::addDelta(DIE *Die, unsigned Attribute, unsigned Form, - const DWLabel &Hi, const DWLabel &Lo) { + const MCSymbol *Hi, const MCSymbol *Lo) { DIEValue *Value = new DIEDelta(Hi, Lo); DIEValues.push_back(Value); Die->addValue(Attribute, Form, Value); @@ -413,11 +406,12 @@ void DwarfDebug::addBlock(DIE *Die, unsigned Attribute, unsigned Form, /// entry. void DwarfDebug::addSourceLine(DIE *Die, const DIVariable *V) { // If there is no compile unit specified, don't add a line #. - if (V->getCompileUnit().isNull()) + if (!V->getCompileUnit().Verify()) return; unsigned Line = V->getLineNumber(); - unsigned FileID = findCompileUnit(V->getCompileUnit())->getID(); + unsigned FileID = GetOrCreateSourceID(V->getContext().getDirectory(), + V->getContext().getFilename()); assert(FileID && "Invalid file id"); addUInt(Die, dwarf::DW_AT_decl_file, 0, FileID); addUInt(Die, dwarf::DW_AT_decl_line, 0, Line); @@ -427,11 +421,12 @@ void DwarfDebug::addSourceLine(DIE *Die, const DIVariable *V) { /// entry. void DwarfDebug::addSourceLine(DIE *Die, const DIGlobal *G) { // If there is no compile unit specified, don't add a line #. - if (G->getCompileUnit().isNull()) + if (!G->getCompileUnit().Verify()) return; unsigned Line = G->getLineNumber(); - unsigned FileID = findCompileUnit(G->getCompileUnit())->getID(); + unsigned FileID = GetOrCreateSourceID(G->getContext().getDirectory(), + G->getContext().getFilename()); assert(FileID && "Invalid file id"); addUInt(Die, dwarf::DW_AT_decl_file, 0, FileID); addUInt(Die, dwarf::DW_AT_decl_line, 0, Line); @@ -441,15 +436,17 @@ void DwarfDebug::addSourceLine(DIE *Die, const DIGlobal *G) { /// entry. void DwarfDebug::addSourceLine(DIE *Die, const DISubprogram *SP) { // If there is no compile unit specified, don't add a line #. - if (SP->getCompileUnit().isNull()) + if (!SP->getCompileUnit().Verify()) return; // If the line number is 0, don't add it. if (SP->getLineNumber() == 0) return; - unsigned Line = SP->getLineNumber(); - unsigned FileID = findCompileUnit(SP->getCompileUnit())->getID(); + if (!SP->getContext().Verify()) + return; + unsigned FileID = GetOrCreateSourceID(SP->getContext().getDirectory(), + SP->getContext().getFilename()); assert(FileID && "Invalid file id"); addUInt(Die, dwarf::DW_AT_decl_file, 0, FileID); addUInt(Die, dwarf::DW_AT_decl_line, 0, Line); @@ -460,11 +457,14 @@ void DwarfDebug::addSourceLine(DIE *Die, const DISubprogram *SP) { void DwarfDebug::addSourceLine(DIE *Die, const DIType *Ty) { // If there is no compile unit specified, don't add a line #. DICompileUnit CU = Ty->getCompileUnit(); - if (CU.isNull()) + if (!CU.Verify()) return; unsigned Line = Ty->getLineNumber(); - unsigned FileID = findCompileUnit(CU)->getID(); + if (!Ty->getContext().Verify()) + return; + unsigned FileID = GetOrCreateSourceID(Ty->getContext().getDirectory(), + Ty->getContext().getFilename()); assert(FileID && "Invalid file id"); addUInt(Die, dwarf::DW_AT_decl_file, 0, FileID); addUInt(Die, dwarf::DW_AT_decl_line, 0, Line); @@ -474,7 +474,7 @@ void DwarfDebug::addSourceLine(DIE *Die, const DIType *Ty) { /// entry. void DwarfDebug::addSourceLine(DIE *Die, const DINameSpace *NS) { // If there is no compile unit specified, don't add a line #. - if (NS->getCompileUnit().isNull()) + if (!NS->getCompileUnit().Verify()) return; unsigned Line = NS->getLineNumber(); @@ -526,12 +526,8 @@ DIType DwarfDebug::getBlockByrefType(DIType Ty, std::string Name) { } DICompositeType blockStruct = DICompositeType(subType.getNode()); - DIArray Elements = blockStruct.getTypeArray(); - if (Elements.isNull()) - return Ty; - for (unsigned i = 0, N = Elements.getNumElements(); i < N; ++i) { DIDescriptor Element = Elements.getElement(i); DIDerivedType DT = DIDerivedType(Element.getNode()); @@ -677,7 +673,6 @@ void DwarfDebug::addBlockByrefAddress(DbgVariable *&DV, DIE *Die, DIDescriptor varField = DIDescriptor(); DIDescriptor forwardingField = DIDescriptor(); - for (unsigned i = 0, N = Fields.getNumElements(); i < N; ++i) { DIDescriptor Element = Fields.getElement(i); DIDerivedType DT = DIDerivedType(Element.getNode()); @@ -688,10 +683,6 @@ void DwarfDebug::addBlockByrefAddress(DbgVariable *&DV, DIE *Die, varField = Element; } - assert(!varField.isNull() && "Can't find byref variable in Block struct"); - assert(!forwardingField.isNull() - && "Can't find forwarding field in Block struct"); - // Get the offsets for the forwarding field and the variable field. unsigned int forwardingFieldOffset = DIDerivedType(forwardingField.getNode()).getOffsetInBits() >> 3; @@ -781,9 +772,7 @@ void DwarfDebug::addAddress(DIE *Die, unsigned Attribute, /// addToContextOwner - Add Die into the list of its context owner's children. void DwarfDebug::addToContextOwner(DIE *Die, DIDescriptor Context) { - if (Context.isNull()) - ModuleCU->addDie(Die); - else if (Context.isType()) { + if (Context.isType()) { DIE *ContextDIE = getOrCreateTypeDIE(DIType(Context.getNode())); ContextDIE->addChild(Die); } else if (Context.isNameSpace()) { @@ -820,7 +809,7 @@ DIE *DwarfDebug::getOrCreateTypeDIE(DIType Ty) { /// addType - Add a new type attribute to the specified entity. void DwarfDebug::addType(DIE *Entity, DIType Ty) { - if (Ty.isNull()) + if (!Ty.isValid()) return; // Check for pre-existence. @@ -906,9 +895,9 @@ void DwarfDebug::constructTypeDIE(DIE &Buffer, DICompositeType CTy) { // Add enumerators to enumeration type. for (unsigned i = 0, N = Elements.getNumElements(); i < N; ++i) { DIE *ElemDie = NULL; - DIEnumerator Enum(Elements.getElement(i).getNode()); - if (!Enum.isNull()) { - ElemDie = constructEnumTypeDIE(&Enum); + DIDescriptor Enum(Elements.getElement(i).getNode()); + if (Enum.isEnumerator()) { + ElemDie = constructEnumTypeDIE(DIEnumerator(Enum.getNode())); Buffer.addChild(ElemDie); } } @@ -939,18 +928,17 @@ void DwarfDebug::constructTypeDIE(DIE &Buffer, DICompositeType CTy) { DIArray Elements = CTy.getTypeArray(); // A forward struct declared type may not have elements available. - if (Elements.isNull()) + unsigned N = Elements.getNumElements(); + if (N == 0) break; // Add elements to structure type. - for (unsigned i = 0, N = Elements.getNumElements(); i < N; ++i) { + for (unsigned i = 0; i < N; ++i) { DIDescriptor Element = Elements.getElement(i); - if (Element.isNull()) - continue; DIE *ElemDie = NULL; - if (Element.getTag() == dwarf::DW_TAG_subprogram) + if (Element.isSubprogram()) ElemDie = createSubprogramDIE(DISubprogram(Element.getNode())); - else if (Element.getTag() == dwarf::DW_TAG_auto_variable) { + else if (Element.isVariable()) { DIVariable DV(Element.getNode()); ElemDie = new DIE(dwarf::DW_TAG_variable); addString(ElemDie, dwarf::DW_AT_name, dwarf::DW_FORM_string, @@ -959,8 +947,10 @@ void DwarfDebug::constructTypeDIE(DIE &Buffer, DICompositeType CTy) { addUInt(ElemDie, dwarf::DW_AT_declaration, dwarf::DW_FORM_flag, 1); addUInt(ElemDie, dwarf::DW_AT_external, dwarf::DW_FORM_flag, 1); addSourceLine(ElemDie, &DV); - } else + } else if (Element.isDerivedType()) ElemDie = createMemberDIE(DIDerivedType(Element.getNode())); + else + continue; Buffer.addChild(ElemDie); } @@ -973,7 +963,7 @@ void DwarfDebug::constructTypeDIE(DIE &Buffer, DICompositeType CTy) { dwarf::DW_FORM_data1, RLang); DICompositeType ContainingType = CTy.getContainingType(); - if (!ContainingType.isNull()) + if (DIDescriptor(ContainingType.getNode()).isCompositeType()) addDIEEntry(&Buffer, dwarf::DW_AT_containing_type, dwarf::DW_FORM_ref4, getOrCreateTypeDIE(DIType(ContainingType.getNode()))); break; @@ -1051,11 +1041,11 @@ void DwarfDebug::constructArrayTypeDIE(DIE &Buffer, } /// constructEnumTypeDIE - Construct enum type DIE from DIEnumerator. -DIE *DwarfDebug::constructEnumTypeDIE(DIEnumerator *ETy) { +DIE *DwarfDebug::constructEnumTypeDIE(DIEnumerator ETy) { DIE *Enumerator = new DIE(dwarf::DW_TAG_enumerator); - StringRef Name = ETy->getName(); + StringRef Name = ETy.getName(); addString(Enumerator, dwarf::DW_AT_name, dwarf::DW_FORM_string, Name); - int64_t Value = ETy->getEnumValue(); + int64_t Value = ETy.getEnumValue(); addSInt(Enumerator, dwarf::DW_AT_const_value, dwarf::DW_FORM_sdata, Value); return Enumerator; } @@ -1199,7 +1189,7 @@ DIE *DwarfDebug::createSubprogramDIE(const DISubprogram &SP, bool MakeDecl) { DIArray Args = SPTy.getTypeArray(); unsigned SPTag = SPTy.getTag(); - if (Args.isNull() || SPTag != dwarf::DW_TAG_subroutine_type) + if (Args.getNumElements() == 0 || SPTag != dwarf::DW_TAG_subroutine_type) addType(SPDie, SPTy); else addType(SPDie, DIType(Args.getElement(0).getNode())); @@ -1243,16 +1233,6 @@ DIE *DwarfDebug::createSubprogramDIE(const DISubprogram &SP, bool MakeDecl) { return SPDie; } -/// findCompileUnit - Get the compile unit for the given descriptor. -/// -CompileUnit *DwarfDebug::findCompileUnit(DICompileUnit Unit) { - DenseMap<Value *, CompileUnit *>::const_iterator I = - CompileUnitMap.find(Unit.getNode()); - if (I == CompileUnitMap.end()) - return constructCompileUnit(Unit.getNode()); - return I->second; -} - /// getUpdatedDbgScope - Find or create DbgScope assicated with the instruction. /// Initialize scope and update scope hierarchy. DbgScope *DwarfDebug::getUpdatedDbgScope(MDNode *N, const MachineInstr *MI, @@ -1282,11 +1262,9 @@ DbgScope *DwarfDebug::getUpdatedDbgScope(MDNode *N, const MachineInstr *MI, Parent->addScope(NScope); } else if (DIDescriptor(N).isLexicalBlock()) { DILexicalBlock DB(N); - if (!DB.getContext().isNull()) { - Parent = getUpdatedDbgScope(DB.getContext().getNode(), MI, InlinedAt); - NScope->setParent(Parent); - Parent->addScope(NScope); - } + Parent = getUpdatedDbgScope(DB.getContext().getNode(), MI, InlinedAt); + NScope->setParent(Parent); + Parent->addScope(NScope); } NScope->setFirstInsn(MI); @@ -1318,8 +1296,7 @@ DbgScope *DwarfDebug::getOrCreateAbstractScope(MDNode *N) { if (Scope.isLexicalBlock()) { DILexicalBlock DB(N); DIDescriptor ParentDesc = DB.getContext(); - if (!ParentDesc.isNull()) - Parent = getOrCreateAbstractScope(ParentDesc.getNode()); + Parent = getOrCreateAbstractScope(ParentDesc.getNode()); } AScope = new DbgScope(Parent, DIDescriptor(N), NULL); @@ -1371,9 +1348,9 @@ DIE *DwarfDebug::updateSubprogramScopeDIE(MDNode *SPNode) { } addLabel(SPDie, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr, - DWLabel("func_begin", SubprogramCount)); + getDWLabel("func_begin", SubprogramCount)); addLabel(SPDie, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr, - DWLabel("func_end", SubprogramCount)); + getDWLabel("func_end", SubprogramCount)); MachineLocation Location(RI->getFrameRegister(*MF)); addAddress(SPDie, dwarf::DW_AT_frame_base, Location); @@ -1386,27 +1363,21 @@ DIE *DwarfDebug::updateSubprogramScopeDIE(MDNode *SPNode) { /// constructLexicalScope - Construct new DW_TAG_lexical_block /// for this scope and attach DW_AT_low_pc/DW_AT_high_pc labels. DIE *DwarfDebug::constructLexicalScopeDIE(DbgScope *Scope) { - unsigned StartID = MMI->MappedLabel(Scope->getStartLabelID()); - unsigned EndID = MMI->MappedLabel(Scope->getEndLabelID()); - - // Ignore empty scopes. - if (StartID == EndID && StartID != 0) - return NULL; + MCSymbol *Start = Scope->getStartLabel(); + MCSymbol *End = Scope->getEndLabel(); + if (Start == 0) return 0; + assert(Start->isDefined() && "Invalid starting label for an inlined scope!"); + assert(End->isDefined() && "Invalid end label for an inlined scope!"); + DIE *ScopeDIE = new DIE(dwarf::DW_TAG_lexical_block); if (Scope->isAbstractScope()) return ScopeDIE; addLabel(ScopeDIE, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr, - StartID ? - DWLabel("label", StartID) - : DWLabel("func_begin", SubprogramCount)); + Start ? Start : getDWLabel("func_begin", SubprogramCount)); addLabel(ScopeDIE, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr, - EndID ? - DWLabel("label", EndID) - : DWLabel("func_end", SubprogramCount)); - - + End ? End : getDWLabel("func_end", SubprogramCount)); return ScopeDIE; } @@ -1415,17 +1386,17 @@ DIE *DwarfDebug::constructLexicalScopeDIE(DbgScope *Scope) { /// a function. Construct DIE to represent this concrete inlined copy /// of the function. DIE *DwarfDebug::constructInlinedScopeDIE(DbgScope *Scope) { - unsigned StartID = MMI->MappedLabel(Scope->getStartLabelID()); - unsigned EndID = MMI->MappedLabel(Scope->getEndLabelID()); - assert (StartID && "Invalid starting label for an inlined scope!"); - assert (EndID && "Invalid end label for an inlined scope!"); - // Ignore empty scopes. - if (StartID == EndID && StartID != 0) + MCSymbol *StartLabel = Scope->getStartLabel(); + MCSymbol *EndLabel = Scope->getEndLabel(); + if (StartLabel == 0) return 0; + + assert(StartLabel->isDefined() && + "Invalid starting label for an inlined scope!"); + assert(EndLabel->isDefined() && + "Invalid end label for an inlined scope!"); + if (!Scope->getScopeNode()) return NULL; - DIScope DS(Scope->getScopeNode()); - if (DS.isNull()) - return NULL; DIE *ScopeDIE = new DIE(dwarf::DW_TAG_inlined_subroutine); DISubprogram InlinedSP = getDISubprogram(DS.getNode()); @@ -1434,10 +1405,8 @@ DIE *DwarfDebug::constructInlinedScopeDIE(DbgScope *Scope) { addDIEEntry(ScopeDIE, dwarf::DW_AT_abstract_origin, dwarf::DW_FORM_ref4, OriginDIE); - addLabel(ScopeDIE, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr, - DWLabel("label", StartID)); - addLabel(ScopeDIE, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr, - DWLabel("label", EndID)); + addLabel(ScopeDIE, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr, StartLabel); + addLabel(ScopeDIE, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr, EndLabel); InlinedSubprogramDIEs.insert(OriginDIE); @@ -1446,11 +1415,11 @@ DIE *DwarfDebug::constructInlinedScopeDIE(DbgScope *Scope) { I = InlineInfo.find(InlinedSP.getNode()); if (I == InlineInfo.end()) { - InlineInfo[InlinedSP.getNode()].push_back(std::make_pair(StartID, + InlineInfo[InlinedSP.getNode()].push_back(std::make_pair(StartLabel, ScopeDIE)); InlinedSPNodes.push_back(InlinedSP.getNode()); } else - I->second.push_back(std::make_pair(StartID, ScopeDIE)); + I->second.push_back(std::make_pair(StartLabel, ScopeDIE)); StringPool.insert(InlinedSP.getName()); StringPool.insert(getRealLinkageName(InlinedSP.getLinkageName())); @@ -1547,15 +1516,12 @@ void DwarfDebug::addPubTypes(DISubprogram SP) { return; DIArray Args = SPTy.getTypeArray(); - if (Args.isNull()) - return; - for (unsigned i = 0, e = Args.getNumElements(); i != e; ++i) { DIType ATy(Args.getElement(i).getNode()); - if (ATy.isNull()) + if (!ATy.isValid()) continue; DICompositeType CATy = getDICompositeType(ATy); - if (!CATy.isNull() && !CATy.getName().empty()) { + if (DIDescriptor(CATy.getNode()).Verify() && !CATy.getName().empty()) { if (DIEEntry *Entry = ModuleCU->getDIEEntry(CATy.getNode())) ModuleCU->addGlobalType(CATy.getName(), Entry->getEntry()); } @@ -1564,26 +1530,24 @@ void DwarfDebug::addPubTypes(DISubprogram SP) { /// constructScopeDIE - Construct a DIE for this scope. DIE *DwarfDebug::constructScopeDIE(DbgScope *Scope) { - if (!Scope) - return NULL; - DIScope DS(Scope->getScopeNode()); - if (DS.isNull()) - return NULL; - - DIE *ScopeDIE = NULL; - if (Scope->getInlinedAt()) - ScopeDIE = constructInlinedScopeDIE(Scope); - else if (DS.isSubprogram()) { - if (Scope->isAbstractScope()) - ScopeDIE = ModuleCU->getDIE(DS.getNode()); - else - ScopeDIE = updateSubprogramScopeDIE(DS.getNode()); - } - else { - ScopeDIE = constructLexicalScopeDIE(Scope); - if (!ScopeDIE) return NULL; - } - + if (!Scope || !Scope->getScopeNode()) + return NULL; + + DIScope DS(Scope->getScopeNode()); + DIE *ScopeDIE = NULL; + if (Scope->getInlinedAt()) + ScopeDIE = constructInlinedScopeDIE(Scope); + else if (DS.isSubprogram()) { + if (Scope->isAbstractScope()) + ScopeDIE = ModuleCU->getDIE(DS.getNode()); + else + ScopeDIE = updateSubprogramScopeDIE(DS.getNode()); + } + else { + ScopeDIE = constructLexicalScopeDIE(Scope); + if (!ScopeDIE) return NULL; + } + // Add variables to scope. SmallVector<DbgVariable *, 8> &Variables = Scope->getVariables(); for (unsigned i = 0, N = Variables.size(); i < N; ++i) { @@ -1665,8 +1629,9 @@ CompileUnit *DwarfDebug::constructCompileUnit(MDNode *N) { unsigned ID = GetOrCreateSourceID(Dir, FN); DIE *Die = new DIE(dwarf::DW_TAG_compile_unit); + // FIXME: Why getting the delta between two identical labels?? addSectionOffset(Die, dwarf::DW_AT_stmt_list, dwarf::DW_FORM_data4, - DWLabel("section_line", 0), DWLabel("section_line", 0), + getTempLabel("section_line"), getTempLabel("section_line"), false); addString(Die, dwarf::DW_AT_producer, dwarf::DW_FORM_string, DIUnit.getProducer()); @@ -1695,8 +1660,6 @@ CompileUnit *DwarfDebug::constructCompileUnit(MDNode *N) { ModuleCU = Unit; } - CompileUnitMap[DIUnit.getNode()] = Unit; - CompileUnits.push_back(Unit); return Unit; } @@ -1730,16 +1693,16 @@ void DwarfDebug::constructGlobalVariableDIE(MDNode *N) { dwarf::DW_FORM_ref4, VariableDie); DIEBlock *Block = new DIEBlock(); addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_addr); - addObjectLabel(Block, 0, dwarf::DW_FORM_udata, - Asm->GetGlobalValueSymbol(DI_GV.getGlobal())); + addLabel(Block, 0, dwarf::DW_FORM_udata, + Asm->GetGlobalValueSymbol(DI_GV.getGlobal())); addBlock(VariableSpecDIE, dwarf::DW_AT_location, 0, Block); addUInt(VariableDie, dwarf::DW_AT_declaration, dwarf::DW_FORM_flag, 1); ModuleCU->addDie(VariableSpecDIE); } else { DIEBlock *Block = new DIEBlock(); addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_addr); - addObjectLabel(Block, 0, dwarf::DW_FORM_udata, - Asm->GetGlobalValueSymbol(DI_GV.getGlobal())); + addLabel(Block, 0, dwarf::DW_FORM_udata, + Asm->GetGlobalValueSymbol(DI_GV.getGlobal())); addBlock(VariableDie, dwarf::DW_AT_location, 0, Block); } addToContextOwner(VariableDie, GVContext); @@ -1802,17 +1765,8 @@ void DwarfDebug::beginModule(Module *M, MachineModuleInfo *mmi) { E = DbgFinder.compile_unit_end(); I != E; ++I) constructCompileUnit(*I); - if (CompileUnits.empty()) { - if (TimePassesIsEnabled) - DebugTimer->stopTimer(); - - return; - } - - // If main compile unit for this module is not seen than randomly - // select first compile unit. if (!ModuleCU) - ModuleCU = CompileUnits[0]; + return; // Create DIEs for each subprogram. for (DebugInfoFinder::iterator I = DbgFinder.subprogram_begin(), @@ -1890,14 +1844,14 @@ void DwarfDebug::endModule() { // Standard sections final addresses. Asm->OutStreamer.SwitchSection(Asm->getObjFileLowering().getTextSection()); - EmitLabel("text_end", 0); + Asm->OutStreamer.EmitLabel(getTempLabel("text_end")); Asm->OutStreamer.SwitchSection(Asm->getObjFileLowering().getDataSection()); - EmitLabel("data_end", 0); + Asm->OutStreamer.EmitLabel(getTempLabel("data_end")); // End text sections. for (unsigned i = 1, N = SectionMap.size(); i <= N; ++i) { Asm->OutStreamer.SwitchSection(SectionMap[i]); - EmitLabel("section_end", i); + Asm->OutStreamer.EmitLabel(getDWLabel("section_end", i)); } // Emit common frame information. @@ -1997,14 +1951,14 @@ void DwarfDebug::collectVariableInfo() { } /// beginScope - Process beginning of a scope starting at Label. -void DwarfDebug::beginScope(const MachineInstr *MI, unsigned Label) { +void DwarfDebug::beginScope(const MachineInstr *MI, MCSymbol *Label) { InsnToDbgScopeMapTy::iterator I = DbgScopeBeginMap.find(MI); if (I == DbgScopeBeginMap.end()) return; ScopeVector &SD = I->second; for (ScopeVector::iterator SDI = SD.begin(), SDE = SD.end(); SDI != SDE; ++SDI) - (*SDI)->setStartLabelID(Label); + (*SDI)->setStartLabel(Label); } /// endScope - Process end of a scope. @@ -2013,14 +1967,13 @@ void DwarfDebug::endScope(const MachineInstr *MI) { if (I == DbgScopeEndMap.end()) return; - unsigned Label = MMI->NextLabelID(); - Asm->printLabel(Label); - O << '\n'; + MCSymbol *Label = getDWLabel("label", MMI->NextLabelID()); + Asm->OutStreamer.EmitLabel(Label); - SmallVector<DbgScope *, 2> &SD = I->second; + SmallVector<DbgScope*, 2> &SD = I->second; for (SmallVector<DbgScope *, 2>::iterator SDI = SD.begin(), SDE = SD.end(); SDI != SDE; ++SDI) - (*SDI)->setEndLabelID(Label); + (*SDI)->setEndLabel(Label); return; } @@ -2069,7 +2022,6 @@ bool DwarfDebug::extractScopeInformation() { if (DL.isUnknown()) continue; DILocation DLT = MF->getDILocation(DL); DIScope DLTScope = DLT.getScope(); - if (DLTScope.isNull()) continue; // There is no need to create another DIE for compile unit. For all // other scopes, create one DbgScope now. This will be translated // into a scope DIE at the end. @@ -2089,7 +2041,6 @@ bool DwarfDebug::extractScopeInformation() { if (DL.isUnknown()) continue; DILocation DLT = MF->getDILocation(DL); DIScope DLTScope = DLT.getScope(); - if (DLTScope.isNull()) continue; // There is no need to create another DIE for compile unit. For all // other scopes, create one DbgScope now. This will be translated // into a scope DIE at the end. @@ -2159,24 +2110,24 @@ void DwarfDebug::beginFunction(const MachineFunction *MF) { collectVariableInfo(); // Assumes in correct section after the entry point. - EmitLabel("func_begin", ++SubprogramCount); + Asm->OutStreamer.EmitLabel(getDWLabel("func_begin", ++SubprogramCount)); // Emit label for the implicitly defined dbg.stoppoint at the start of the // function. DebugLoc FDL = MF->getDefaultDebugLoc(); if (!FDL.isUnknown()) { DILocation DLT = MF->getDILocation(FDL); - unsigned LabelID = 0; DISubprogram SP = getDISubprogram(DLT.getScope().getNode()); - if (!SP.isNull()) - LabelID = recordSourceLine(SP.getLineNumber(), 0, - DLT.getScope().getNode()); - else - LabelID = recordSourceLine(DLT.getLineNumber(), - DLT.getColumnNumber(), - DLT.getScope().getNode()); - Asm->printLabel(LabelID); - O << '\n'; + unsigned Line, Col; + if (SP.Verify()) { + Line = SP.getLineNumber(); + Col = 0; + } else { + Line = DLT.getLineNumber(); + Col = DLT.getColumnNumber(); + } + + recordSourceLine(Line, Col, DLT.getScope().getNode()); } if (TimePassesIsEnabled) DebugTimer->stopTimer(); @@ -2195,7 +2146,7 @@ void DwarfDebug::endFunction(const MachineFunction *MF) { if (CurrentFnDbgScope) { // Define end label for subprogram. - EmitLabel("func_end", SubprogramCount); + Asm->OutStreamer.EmitLabel(getDWLabel("func_end", SubprogramCount)); // Get function line info. if (!Lines.empty()) { @@ -2232,11 +2183,10 @@ void DwarfDebug::endFunction(const MachineFunction *MF) { DebugTimer->stopTimer(); } -/// recordSourceLine - Records location information and associates it with a -/// label. Returns a unique label ID used to generate a label and provide -/// correspondence to the source line list. -unsigned DwarfDebug::recordSourceLine(unsigned Line, unsigned Col, - MDNode *S) { +/// recordSourceLine - Register a source line with debug info. Returns the +/// unique label that was emitted and which provides correspondence to +/// the source line list. +MCSymbol *DwarfDebug::recordSourceLine(unsigned Line, unsigned Col, MDNode *S) { if (!MMI) return 0; @@ -2269,7 +2219,9 @@ unsigned DwarfDebug::recordSourceLine(unsigned Line, unsigned Col, if (TimePassesIsEnabled) DebugTimer->stopTimer(); - return ID; + MCSymbol *Label = getDWLabel("label", ID); + Asm->OutStreamer.EmitLabel(Label); + return Label; } /// getOrCreateSourceID - Public version of GetOrCreateSourceID. This can be @@ -2367,38 +2319,38 @@ void DwarfDebug::emitInitial() { // Dwarf sections base addresses. if (MAI->doesDwarfRequireFrameSection()) { Asm->OutStreamer.SwitchSection(TLOF.getDwarfFrameSection()); - EmitLabel("section_debug_frame", 0); + Asm->OutStreamer.EmitLabel(getTempLabel("section_debug_frame")); } Asm->OutStreamer.SwitchSection(TLOF.getDwarfInfoSection()); - EmitLabel("section_info", 0); + Asm->OutStreamer.EmitLabel(getTempLabel("section_info")); Asm->OutStreamer.SwitchSection(TLOF.getDwarfAbbrevSection()); - EmitLabel("section_abbrev", 0); + Asm->OutStreamer.EmitLabel(getTempLabel("section_abbrev")); Asm->OutStreamer.SwitchSection(TLOF.getDwarfARangesSection()); - EmitLabel("section_aranges", 0); + Asm->OutStreamer.EmitLabel(getTempLabel("section_aranges")); if (const MCSection *LineInfoDirective = TLOF.getDwarfMacroInfoSection()) { Asm->OutStreamer.SwitchSection(LineInfoDirective); - EmitLabel("section_macinfo", 0); + Asm->OutStreamer.EmitLabel(getTempLabel("section_macinfo")); } Asm->OutStreamer.SwitchSection(TLOF.getDwarfLineSection()); - EmitLabel("section_line", 0); + Asm->OutStreamer.EmitLabel(getTempLabel("section_line")); Asm->OutStreamer.SwitchSection(TLOF.getDwarfLocSection()); - EmitLabel("section_loc", 0); + Asm->OutStreamer.EmitLabel(getTempLabel("section_loc")); Asm->OutStreamer.SwitchSection(TLOF.getDwarfPubNamesSection()); - EmitLabel("section_pubnames", 0); + Asm->OutStreamer.EmitLabel(getTempLabel("section_pubnames")); Asm->OutStreamer.SwitchSection(TLOF.getDwarfPubTypesSection()); - EmitLabel("section_pubtypes", 0); + Asm->OutStreamer.EmitLabel(getTempLabel("section_pubtypes")); Asm->OutStreamer.SwitchSection(TLOF.getDwarfStrSection()); - EmitLabel("section_str", 0); + Asm->OutStreamer.EmitLabel(getTempLabel("section_str")); Asm->OutStreamer.SwitchSection(TLOF.getDwarfRangesSection()); - EmitLabel("section_ranges", 0); + Asm->OutStreamer.EmitLabel(getTempLabel("section_ranges")); Asm->OutStreamer.SwitchSection(TLOF.getTextSection()); - EmitLabel("text_begin", 0); + Asm->OutStreamer.EmitLabel(getTempLabel("text_begin")); Asm->OutStreamer.SwitchSection(TLOF.getDataSection()); - EmitLabel("data_begin", 0); + Asm->OutStreamer.EmitLabel(getTempLabel("data_begin")); } /// emitDIE - Recusively Emits a debug information entry. @@ -2408,8 +2360,6 @@ void DwarfDebug::emitDIE(DIE *Die) { unsigned AbbrevNumber = Die->getAbbrevNumber(); const DIEAbbrev *Abbrev = Abbreviations[AbbrevNumber - 1]; - Asm->O << '\n'; - // Emit the code (index) for the abbreviation. if (Asm->VerboseAsm) Asm->OutStreamer.AddComment("Abbrev [" + Twine(AbbrevNumber) + "] 0x" + @@ -2444,7 +2394,6 @@ void DwarfDebug::emitDIE(DIE *Die) { default: // Emit an attribute using the defined form. Values[i]->EmitValue(this, Form); - O << "\n"; // REMOVE This once all EmitValue impls emit their own newline. break; } } @@ -2456,7 +2405,9 @@ void DwarfDebug::emitDIE(DIE *Die) { for (unsigned j = 0, M = Children.size(); j < M; ++j) emitDIE(Children[j]); - Asm->EmitInt8(0); EOL("End Of Children Mark"); + if (Asm->VerboseAsm) + Asm->OutStreamer.AddComment("End Of Children Mark"); + Asm->EmitInt8(0); } } @@ -2469,7 +2420,7 @@ void DwarfDebug::emitDebugInfo() { DIE *Die = ModuleCU->getCUDie(); // Emit the compile units header. - EmitLabel("info_begin", ModuleCU->getID()); + Asm->OutStreamer.EmitLabel(getDWLabel("info_begin", ModuleCU->getID())); // Emit size of content not including length itself unsigned ContentSize = Die->getSize() + @@ -2478,20 +2429,24 @@ void DwarfDebug::emitDebugInfo() { sizeof(int8_t) + // Pointer Size (in bytes) sizeof(int32_t); // FIXME - extra pad for gdb bug. - Asm->EmitInt32(ContentSize); EOL("Length of Compilation Unit Info"); - Asm->EmitInt16(dwarf::DWARF_VERSION); EOL("DWARF version number"); - EmitSectionOffset("abbrev_begin", "section_abbrev", 0, 0, true, false); - EOL("Offset Into Abbrev. Section"); - Asm->EmitInt8(TD->getPointerSize()); EOL("Address Size (in bytes)"); + Asm->OutStreamer.AddComment("Length of Compilation Unit Info"); + Asm->EmitInt32(ContentSize); + Asm->OutStreamer.AddComment("DWARF version number"); + Asm->EmitInt16(dwarf::DWARF_VERSION); + Asm->OutStreamer.AddComment("Offset Into Abbrev. Section"); + EmitSectionOffset(getTempLabel("abbrev_begin"),getTempLabel("section_abbrev"), + true, false); + Asm->OutStreamer.AddComment("Address Size (in bytes)"); + Asm->EmitInt8(TD->getPointerSize()); emitDIE(Die); // FIXME - extra padding for gdb bug. - Asm->EmitInt8(0); EOL("Extra Pad For GDB"); - Asm->EmitInt8(0); EOL("Extra Pad For GDB"); - Asm->EmitInt8(0); EOL("Extra Pad For GDB"); - Asm->EmitInt8(0); EOL("Extra Pad For GDB"); - EmitLabel("info_end", ModuleCU->getID()); - Asm->O << '\n'; + Asm->OutStreamer.AddComment("4 extra padding bytes for GDB"); + Asm->EmitInt8(0); + Asm->EmitInt8(0); + Asm->EmitInt8(0); + Asm->EmitInt8(0); + Asm->OutStreamer.EmitLabel(getDWLabel("info_end", ModuleCU->getID())); } /// emitAbbreviations - Emit the abbreviation section. @@ -2503,7 +2458,7 @@ void DwarfDebug::emitAbbreviations() const { Asm->OutStreamer.SwitchSection( Asm->getObjFileLowering().getDwarfAbbrevSection()); - EmitLabel("abbrev_begin", 0); + Asm->OutStreamer.EmitLabel(getTempLabel("abbrev_begin")); // For each abbrevation. for (unsigned i = 0, N = Abbreviations.size(); i < N; ++i) { @@ -2515,14 +2470,12 @@ void DwarfDebug::emitAbbreviations() const { // Emit the abbreviations data. Abbrev->Emit(this); - Asm->O << '\n'; } // Mark end of abbreviations. EmitULEB128(0, "EOM(3)"); - EmitLabel("abbrev_end", 0); - Asm->O << '\n'; + Asm->OutStreamer.EmitLabel(getTempLabel("abbrev_end")); } } @@ -2531,13 +2484,22 @@ void DwarfDebug::emitAbbreviations() const { /// void DwarfDebug::emitEndOfLineMatrix(unsigned SectionEnd) { // Define last address of section. - Asm->EmitInt8(0); EOL("Extended Op"); - Asm->EmitInt8(TD->getPointerSize() + 1); EOL("Op size"); - Asm->EmitInt8(dwarf::DW_LNE_set_address); EOL("DW_LNE_set_address"); - EmitReference("section_end", SectionEnd); EOL("Section end label"); + Asm->OutStreamer.AddComment("Extended Op"); + Asm->EmitInt8(0); + + Asm->OutStreamer.AddComment("Op size"); + Asm->EmitInt8(TD->getPointerSize() + 1); + Asm->OutStreamer.AddComment("DW_LNE_set_address"); + Asm->EmitInt8(dwarf::DW_LNE_set_address); + + Asm->OutStreamer.AddComment("Section end label"); + + Asm->OutStreamer.EmitSymbolValue(getDWLabel("section_end", SectionEnd), + TD->getPointerSize(), 0/*AddrSpace*/); // Mark end of matrix. - Asm->EmitInt8(0); EOL("DW_LNE_end_sequence"); + Asm->OutStreamer.AddComment("DW_LNE_end_sequence"); + Asm->EmitInt8(0); Asm->EmitInt8(1); Asm->EmitInt8(1); } @@ -2560,32 +2522,48 @@ void DwarfDebug::emitDebugLines() { Asm->getObjFileLowering().getDwarfLineSection()); // Construct the section header. - EmitDifference("line_end", 0, "line_begin", 0, true); - EOL("Length of Source Line Info"); - EmitLabel("line_begin", 0); + Asm->OutStreamer.AddComment("Length of Source Line Info"); + EmitDifference(getTempLabel("line_end"), getTempLabel("line_begin"), true); + Asm->OutStreamer.EmitLabel(getTempLabel("line_begin")); - Asm->EmitInt16(dwarf::DWARF_VERSION); EOL("DWARF version number"); + Asm->OutStreamer.AddComment("DWARF version number"); + Asm->EmitInt16(dwarf::DWARF_VERSION); - EmitDifference("line_prolog_end", 0, "line_prolog_begin", 0, true); - EOL("Prolog Length"); - EmitLabel("line_prolog_begin", 0); + Asm->OutStreamer.AddComment("Prolog Length"); + EmitDifference(getTempLabel("line_prolog_end"), + getTempLabel("line_prolog_begin"), true); + Asm->OutStreamer.EmitLabel(getTempLabel("line_prolog_begin")); - Asm->EmitInt8(1); EOL("Minimum Instruction Length"); - Asm->EmitInt8(1); EOL("Default is_stmt_start flag"); - Asm->EmitInt8(MinLineDelta); EOL("Line Base Value (Special Opcodes)"); - Asm->EmitInt8(MaxLineDelta); EOL("Line Range Value (Special Opcodes)"); - Asm->EmitInt8(-MinLineDelta); EOL("Special Opcode Base"); + Asm->OutStreamer.AddComment("Minimum Instruction Length"); + Asm->EmitInt8(1); + Asm->OutStreamer.AddComment("Default is_stmt_start flag"); + Asm->EmitInt8(1); + Asm->OutStreamer.AddComment("Line Base Value (Special Opcodes)"); + Asm->EmitInt8(MinLineDelta); + Asm->OutStreamer.AddComment("Line Range Value (Special Opcodes)"); + Asm->EmitInt8(MaxLineDelta); + Asm->OutStreamer.AddComment("Special Opcode Base"); + Asm->EmitInt8(-MinLineDelta); // Line number standard opcode encodings argument count - Asm->EmitInt8(0); EOL("DW_LNS_copy arg count"); - Asm->EmitInt8(1); EOL("DW_LNS_advance_pc arg count"); - Asm->EmitInt8(1); EOL("DW_LNS_advance_line arg count"); - Asm->EmitInt8(1); EOL("DW_LNS_set_file arg count"); - Asm->EmitInt8(1); EOL("DW_LNS_set_column arg count"); - Asm->EmitInt8(0); EOL("DW_LNS_negate_stmt arg count"); - Asm->EmitInt8(0); EOL("DW_LNS_set_basic_block arg count"); - Asm->EmitInt8(0); EOL("DW_LNS_const_add_pc arg count"); - Asm->EmitInt8(1); EOL("DW_LNS_fixed_advance_pc arg count"); + Asm->OutStreamer.AddComment("DW_LNS_copy arg count"); + Asm->EmitInt8(0); + Asm->OutStreamer.AddComment("DW_LNS_advance_pc arg count"); + Asm->EmitInt8(1); + Asm->OutStreamer.AddComment("DW_LNS_advance_line arg count"); + Asm->EmitInt8(1); + Asm->OutStreamer.AddComment("DW_LNS_set_file arg count"); + Asm->EmitInt8(1); + Asm->OutStreamer.AddComment("DW_LNS_set_column arg count"); + Asm->EmitInt8(1); + Asm->OutStreamer.AddComment("DW_LNS_negate_stmt arg count"); + Asm->EmitInt8(0); + Asm->OutStreamer.AddComment("DW_LNS_set_basic_block arg count"); + Asm->EmitInt8(0); + Asm->OutStreamer.AddComment("DW_LNS_const_add_pc arg count"); + Asm->EmitInt8(0); + Asm->OutStreamer.AddComment("DW_LNS_fixed_advance_pc arg count"); + Asm->EmitInt8(1); // Emit directories. for (unsigned DI = 1, DE = getNumSourceDirectories()+1; DI != DE; ++DI) { @@ -2594,7 +2572,8 @@ void DwarfDebug::emitDebugLines() { Asm->OutStreamer.EmitBytes(StringRef(Dir.c_str(), Dir.size()+1), 0); } - Asm->EmitInt8(0); EOL("End of directories"); + Asm->OutStreamer.AddComment("End of directories"); + Asm->EmitInt8(0); // Emit files. for (unsigned SI = 1, SE = getNumSourceIds()+1; SI != SE; ++SI) { @@ -2609,9 +2588,10 @@ void DwarfDebug::emitDebugLines() { EmitULEB128(0, "File size"); } - Asm->EmitInt8(0); EOL("End of files"); + Asm->OutStreamer.AddComment("End of files"); + Asm->EmitInt8(0); - EmitLabel("line_prolog_end", 0); + Asm->OutStreamer.EmitLabel(getTempLabel("line_prolog_end")); // A sequence for each text section. unsigned SecSrcLinesSize = SectionSourceLines.size(); @@ -2620,13 +2600,6 @@ void DwarfDebug::emitDebugLines() { // Isolate current sections line info. const std::vector<SrcLineInfo> &LineInfos = SectionSourceLines[j]; - /*if (Asm->isVerbose()) { - const MCSection *S = SectionMap[j + 1]; - O << '\t' << MAI->getCommentString() << " Section" - << S->getName() << '\n'; - }*/ - Asm->O << '\n'; - // Dwarf assumes we start with first line of first source file. unsigned Source = 1; unsigned Line = 1; @@ -2634,32 +2607,38 @@ void DwarfDebug::emitDebugLines() { // Construct rows of the address, source, line, column matrix. for (unsigned i = 0, N = LineInfos.size(); i < N; ++i) { const SrcLineInfo &LineInfo = LineInfos[i]; - unsigned LabelID = MMI->MappedLabel(LineInfo.getLabelID()); - if (!LabelID) continue; + unsigned LabelID = LineInfo.getLabelID(); + if (MMI->isLabelDeleted(LabelID)) continue; if (LineInfo.getLine() == 0) continue; - if (!Asm->isVerbose()) - Asm->O << '\n'; - else { - std::pair<unsigned, unsigned> SourceID = + if (Asm->isVerbose()) { + std::pair<unsigned, unsigned> SrcID = getSourceDirectoryAndFileIds(LineInfo.getSourceID()); - O << '\t' << MAI->getCommentString() << ' ' - << getSourceDirectoryName(SourceID.first) << '/' - << getSourceFileName(SourceID.second) - << ':' << utostr_32(LineInfo.getLine()) << '\n'; + Asm->OutStreamer.AddComment(Twine(getSourceDirectoryName(SrcID.first)) + + "/" + + Twine(getSourceFileName(SrcID.second)) + + ":" + Twine(LineInfo.getLine())); } // Define the line address. - Asm->EmitInt8(0); EOL("Extended Op"); - Asm->EmitInt8(TD->getPointerSize() + 1); EOL("Op size"); - Asm->EmitInt8(dwarf::DW_LNE_set_address); EOL("DW_LNE_set_address"); - EmitReference("label", LabelID); EOL("Location label"); - + Asm->OutStreamer.AddComment("Extended Op"); + Asm->EmitInt8(0); + Asm->OutStreamer.AddComment("Op size"); + Asm->EmitInt8(TD->getPointerSize() + 1); + + Asm->OutStreamer.AddComment("DW_LNE_set_address"); + Asm->EmitInt8(dwarf::DW_LNE_set_address); + + Asm->OutStreamer.AddComment("Location label"); + Asm->OutStreamer.EmitSymbolValue(getDWLabel("label", LabelID), + TD->getPointerSize(), 0/*AddrSpace*/); + // If change of source, then switch to the new source. if (Source != LineInfo.getSourceID()) { Source = LineInfo.getSourceID(); - Asm->EmitInt8(dwarf::DW_LNS_set_file); EOL("DW_LNS_set_file"); + Asm->OutStreamer.AddComment("DW_LNS_set_file"); + Asm->EmitInt8(dwarf::DW_LNS_set_file); EmitULEB128(Source, "New Source"); } @@ -2675,17 +2654,20 @@ void DwarfDebug::emitDebugLines() { // If delta is small enough and in range... if (Delta >= 0 && Delta < (MaxLineDelta - 1)) { // ... then use fast opcode. - Asm->EmitInt8(Delta - MinLineDelta); EOL("Line Delta"); + Asm->OutStreamer.AddComment("Line Delta"); + Asm->EmitInt8(Delta - MinLineDelta); } else { // ... otherwise use long hand. + Asm->OutStreamer.AddComment("DW_LNS_advance_line"); Asm->EmitInt8(dwarf::DW_LNS_advance_line); - EOL("DW_LNS_advance_line"); EmitSLEB128(Offset, "Line Offset"); - Asm->EmitInt8(dwarf::DW_LNS_copy); EOL("DW_LNS_copy"); + Asm->OutStreamer.AddComment("DW_LNS_copy"); + Asm->EmitInt8(dwarf::DW_LNS_copy); } } else { // Copy the previous row (different address or source) - Asm->EmitInt8(dwarf::DW_LNS_copy); EOL("DW_LNS_copy"); + Asm->OutStreamer.AddComment("DW_LNS_copy"); + Asm->EmitInt8(dwarf::DW_LNS_copy); } } @@ -2698,8 +2680,7 @@ void DwarfDebug::emitDebugLines() { // put into it, emit an empty table. emitEndOfLineMatrix(1); - EmitLabel("line_end", 0); - Asm->O << '\n'; + Asm->OutStreamer.EmitLabel(getTempLabel("line_end")); } /// emitCommonDebugFrame - Emit common frame info into a debug frame section. @@ -2717,22 +2698,22 @@ void DwarfDebug::emitCommonDebugFrame() { Asm->OutStreamer.SwitchSection( Asm->getObjFileLowering().getDwarfFrameSection()); - EmitLabel("debug_frame_common", 0); - EmitDifference("debug_frame_common_end", 0, - "debug_frame_common_begin", 0, true); - EOL("Length of Common Information Entry"); + Asm->OutStreamer.EmitLabel(getTempLabel("debug_frame_common")); + Asm->OutStreamer.AddComment("Length of Common Information Entry"); + EmitDifference(getTempLabel("debug_frame_common_end"), + getTempLabel("debug_frame_common_begin"), true); - EmitLabel("debug_frame_common_begin", 0); + Asm->OutStreamer.EmitLabel(getTempLabel("debug_frame_common_begin")); + Asm->OutStreamer.AddComment("CIE Identifier Tag"); Asm->EmitInt32((int)dwarf::DW_CIE_ID); - EOL("CIE Identifier Tag"); + Asm->OutStreamer.AddComment("CIE Version"); Asm->EmitInt8(dwarf::DW_CIE_VERSION); - EOL("CIE Version"); + Asm->OutStreamer.AddComment("CIE Augmentation"); Asm->OutStreamer.EmitIntValue(0, 1, /*addrspace*/0); // nul terminator. - EOL("CIE Augmentation"); EmitULEB128(1, "CIE Code Alignment Factor"); EmitSLEB128(stackGrowth, "CIE Data Alignment Factor"); + Asm->OutStreamer.AddComment("CIE RA Column"); Asm->EmitInt8(RI->getDwarfRegNum(RI->getRARegister(), false)); - EOL("CIE RA Column"); std::vector<MachineMove> Moves; RI->getInitialFrameState(Moves); @@ -2740,8 +2721,7 @@ void DwarfDebug::emitCommonDebugFrame() { EmitFrameMoves(NULL, 0, Moves, false); Asm->EmitAlignment(2, 0, 0, false); - EmitLabel("debug_frame_common_end", 0); - Asm->O << '\n'; + Asm->OutStreamer.EmitLabel(getTempLabel("debug_frame_common_end")); } /// emitFunctionDebugFrame - Emit per function frame info into a debug frame @@ -2755,28 +2735,34 @@ DwarfDebug::emitFunctionDebugFrame(const FunctionDebugFrameInfo&DebugFrameInfo){ Asm->OutStreamer.SwitchSection( Asm->getObjFileLowering().getDwarfFrameSection()); - EmitDifference("debug_frame_end", DebugFrameInfo.Number, - "debug_frame_begin", DebugFrameInfo.Number, true); - EOL("Length of Frame Information Entry"); + Asm->OutStreamer.AddComment("Length of Frame Information Entry"); + EmitDifference(getDWLabel("debug_frame_end", DebugFrameInfo.Number), + getDWLabel("debug_frame_begin", DebugFrameInfo.Number), true); - EmitLabel("debug_frame_begin", DebugFrameInfo.Number); + Asm->OutStreamer.EmitLabel(getDWLabel("debug_frame_begin", + DebugFrameInfo.Number)); - EmitSectionOffset("debug_frame_common", "section_debug_frame", - 0, 0, true, false); - EOL("FDE CIE offset"); + Asm->OutStreamer.AddComment("FDE CIE offset"); + EmitSectionOffset(getTempLabel("debug_frame_common"), + getTempLabel("section_debug_frame"), true, false); - EmitReference("func_begin", DebugFrameInfo.Number); - EOL("FDE initial location"); - EmitDifference("func_end", DebugFrameInfo.Number, - "func_begin", DebugFrameInfo.Number); - EOL("FDE address range"); + Asm->OutStreamer.AddComment("FDE initial location"); + Asm->OutStreamer.EmitSymbolValue(getDWLabel("func_begin", + DebugFrameInfo.Number), + TD->getPointerSize(), 0/*AddrSpace*/); + + + + Asm->OutStreamer.AddComment("FDE address range"); + EmitDifference(getDWLabel("func_end", DebugFrameInfo.Number), + getDWLabel("func_begin", DebugFrameInfo.Number)); EmitFrameMoves("func_begin", DebugFrameInfo.Number, DebugFrameInfo.Moves, false); Asm->EmitAlignment(2, 0, 0, false); - EmitLabel("debug_frame_end", DebugFrameInfo.Number); - Asm->O << '\n'; + Asm->OutStreamer.EmitLabel(getDWLabel("debug_frame_end", + DebugFrameInfo.Number)); } /// emitDebugPubNames - Emit visible names into a debug pubnames section. @@ -2786,60 +2772,65 @@ void DwarfDebug::emitDebugPubNames() { Asm->OutStreamer.SwitchSection( Asm->getObjFileLowering().getDwarfPubNamesSection()); - EmitDifference("pubnames_end", ModuleCU->getID(), - "pubnames_begin", ModuleCU->getID(), true); - EOL("Length of Public Names Info"); + Asm->OutStreamer.AddComment("Length of Public Names Info"); + EmitDifference(getDWLabel("pubnames_end", ModuleCU->getID()), + getDWLabel("pubnames_begin", ModuleCU->getID()), true); - EmitLabel("pubnames_begin", ModuleCU->getID()); + Asm->OutStreamer.EmitLabel(getDWLabel("pubnames_begin", ModuleCU->getID())); - Asm->EmitInt16(dwarf::DWARF_VERSION); EOL("DWARF Version"); + Asm->OutStreamer.AddComment("DWARF Version"); + Asm->EmitInt16(dwarf::DWARF_VERSION); - EmitSectionOffset("info_begin", "section_info", - ModuleCU->getID(), 0, true, false); - EOL("Offset of Compilation Unit Info"); + Asm->OutStreamer.AddComment("Offset of Compilation Unit Info"); + EmitSectionOffset(getDWLabel("info_begin", ModuleCU->getID()), + getTempLabel("section_info"), + true, false); - EmitDifference("info_end", ModuleCU->getID(), "info_begin", ModuleCU->getID(), + Asm->OutStreamer.AddComment("Compilation Unit Length"); + EmitDifference(getDWLabel("info_end", ModuleCU->getID()), + getDWLabel("info_begin", ModuleCU->getID()), true); - EOL("Compilation Unit Length"); const StringMap<DIE*> &Globals = ModuleCU->getGlobals(); for (StringMap<DIE*>::const_iterator GI = Globals.begin(), GE = Globals.end(); GI != GE; ++GI) { const char *Name = GI->getKeyData(); - DIE * Entity = GI->second; + DIE *Entity = GI->second; - Asm->EmitInt32(Entity->getOffset()); EOL("DIE offset"); + Asm->OutStreamer.AddComment("DIE offset"); + Asm->EmitInt32(Entity->getOffset()); if (Asm->VerboseAsm) Asm->OutStreamer.AddComment("External Name"); Asm->OutStreamer.EmitBytes(StringRef(Name, strlen(Name)+1), 0); } - Asm->EmitInt32(0); EOL("End Mark"); - EmitLabel("pubnames_end", ModuleCU->getID()); - Asm->O << '\n'; + Asm->OutStreamer.AddComment("End Mark"); + Asm->EmitInt32(0); + Asm->OutStreamer.EmitLabel(getDWLabel("pubnames_end", ModuleCU->getID())); } void DwarfDebug::emitDebugPubTypes() { // Start the dwarf pubnames section. Asm->OutStreamer.SwitchSection( Asm->getObjFileLowering().getDwarfPubTypesSection()); - EmitDifference("pubtypes_end", ModuleCU->getID(), - "pubtypes_begin", ModuleCU->getID(), true); - EOL("Length of Public Types Info"); + Asm->OutStreamer.AddComment("Length of Public Types Info"); + EmitDifference(getDWLabel("pubtypes_end", ModuleCU->getID()), + getDWLabel("pubtypes_begin", ModuleCU->getID()), true); - EmitLabel("pubtypes_begin", ModuleCU->getID()); + Asm->OutStreamer.EmitLabel(getDWLabel("pubtypes_begin", ModuleCU->getID())); if (Asm->VerboseAsm) Asm->OutStreamer.AddComment("DWARF Version"); Asm->EmitInt16(dwarf::DWARF_VERSION); - EmitSectionOffset("info_begin", "section_info", - ModuleCU->getID(), 0, true, false); - EOL("Offset of Compilation ModuleCU Info"); + Asm->OutStreamer.AddComment("Offset of Compilation ModuleCU Info"); + EmitSectionOffset(getDWLabel("info_begin", ModuleCU->getID()), + getTempLabel("section_info"), true, false); - EmitDifference("info_end", ModuleCU->getID(), "info_begin", ModuleCU->getID(), + Asm->OutStreamer.AddComment("Compilation ModuleCU Length"); + EmitDifference(getDWLabel("info_end", ModuleCU->getID()), + getDWLabel("info_begin", ModuleCU->getID()), true); - EOL("Compilation ModuleCU Length"); const StringMap<DIE*> &Globals = ModuleCU->getGlobalTypes(); for (StringMap<DIE*>::const_iterator @@ -2854,32 +2845,29 @@ void DwarfDebug::emitDebugPubTypes() { Asm->OutStreamer.EmitBytes(StringRef(Name, GI->getKeyLength()+1), 0); } - Asm->EmitInt32(0); EOL("End Mark"); - EmitLabel("pubtypes_end", ModuleCU->getID()); - Asm->O << '\n'; + Asm->OutStreamer.AddComment("End Mark"); + Asm->EmitInt32(0); + Asm->OutStreamer.EmitLabel(getDWLabel("pubtypes_end", ModuleCU->getID())); } /// emitDebugStr - Emit visible names into a debug str section. /// void DwarfDebug::emitDebugStr() { // Check to see if it is worth the effort. - if (!StringPool.empty()) { - // Start the dwarf str section. - Asm->OutStreamer.SwitchSection( + if (StringPool.empty()) return; + + // Start the dwarf str section. + Asm->OutStreamer.SwitchSection( Asm->getObjFileLowering().getDwarfStrSection()); - // For each of strings in the string pool. - for (unsigned StringID = 1, N = StringPool.size(); - StringID <= N; ++StringID) { - // Emit a label for reference from debug information entries. - EmitLabel("string", StringID); - - // Emit the string itself. - const std::string &String = StringPool[StringID]; - Asm->OutStreamer.EmitBytes(StringRef(String.c_str(), String.size()+1), 0); - } - - Asm->O << '\n'; + // For each of strings in the string pool. + for (unsigned StringID = 1, N = StringPool.size(); StringID <= N; ++StringID){ + // Emit a label for reference from debug information entries. + Asm->OutStreamer.EmitLabel(getDWLabel("string", StringID)); + + // Emit the string itself. + const std::string &String = StringPool[StringID]; + Asm->OutStreamer.EmitBytes(StringRef(String.c_str(), String.size()+1), 0); } } @@ -2897,33 +2885,6 @@ void DwarfDebug::EmitDebugARanges() { // Start the dwarf aranges section. Asm->OutStreamer.SwitchSection( Asm->getObjFileLowering().getDwarfARangesSection()); - - // FIXME - Mock up -#if 0 - CompileUnit *Unit = GetBaseCompileUnit(); - - // Don't include size of length - Asm->EmitInt32(0x1c); EOL("Length of Address Ranges Info"); - - Asm->EmitInt16(dwarf::DWARF_VERSION); EOL("Dwarf Version"); - - EmitReference("info_begin", Unit->getID()); - EOL("Offset of Compilation Unit Info"); - - Asm->EmitInt8(TD->getPointerSize()); EOL("Size of Address"); - - Asm->EmitInt8(0); EOL("Size of Segment Descriptor"); - - Asm->EmitInt16(0); EOL("Pad (1)"); - Asm->EmitInt16(0); EOL("Pad (2)"); - - // Range 1 - EmitReference("text_begin", 0); EOL("Address"); - EmitDifference("text_end", 0, "text_begin", 0, true); EOL("Length"); - - Asm->EmitInt32(0); EOL("EOM (1)"); - Asm->EmitInt32(0); EOL("EOM (2)"); -#endif } /// emitDebugRanges - Emit visible names into a debug ranges section. @@ -2972,14 +2933,16 @@ void DwarfDebug::emitDebugInlineInfo() { Asm->OutStreamer.SwitchSection( Asm->getObjFileLowering().getDwarfDebugInlineSection()); - EmitDifference("debug_inlined_end", 1, - "debug_inlined_begin", 1, true); - EOL("Length of Debug Inlined Information Entry"); + Asm->OutStreamer.AddComment("Length of Debug Inlined Information Entry"); + EmitDifference(getDWLabel("debug_inlined_end", 1), + getDWLabel("debug_inlined_begin", 1), true); - EmitLabel("debug_inlined_begin", 1); + Asm->OutStreamer.EmitLabel(getDWLabel("debug_inlined_begin", 1)); - Asm->EmitInt16(dwarf::DWARF_VERSION); EOL("Dwarf Version"); - Asm->EmitInt8(TD->getPointerSize()); EOL("Address Size (in bytes)"); + Asm->OutStreamer.AddComment("Dwarf Version"); + Asm->EmitInt16(dwarf::DWARF_VERSION); + Asm->OutStreamer.AddComment("Address Size (in bytes)"); + Asm->EmitInt8(TD->getPointerSize()); for (SmallVector<MDNode *, 4>::iterator I = InlinedSPNodes.begin(), E = InlinedSPNodes.end(); I != E; ++I) { @@ -2992,33 +2955,29 @@ void DwarfDebug::emitDebugInlineInfo() { StringRef LName = SP.getLinkageName(); StringRef Name = SP.getName(); + Asm->OutStreamer.AddComment("MIPS linkage name"); if (LName.empty()) { Asm->OutStreamer.EmitBytes(Name, 0); Asm->OutStreamer.EmitIntValue(0, 1, 0); // nul terminator. } else - EmitSectionOffset("string", "section_str", - StringPool.idFor(getRealLinkageName(LName)), false, true); + EmitSectionOffset(getDWLabel("string", + StringPool.idFor(getRealLinkageName(LName))), + getTempLabel("section_str"), true); - EOL("MIPS linkage name"); - EmitSectionOffset("string", "section_str", - StringPool.idFor(Name), false, true); - EOL("Function name"); + Asm->OutStreamer.AddComment("Function name"); + EmitSectionOffset(getDWLabel("string", StringPool.idFor(Name)), + getTempLabel("section_str"), false, true); EmitULEB128(Labels.size(), "Inline count"); for (SmallVector<InlineInfoLabels, 4>::iterator LI = Labels.begin(), LE = Labels.end(); LI != LE; ++LI) { - DIE *SP = LI->second; - Asm->EmitInt32(SP->getOffset()); EOL("DIE offset"); - - if (TD->getPointerSize() == sizeof(int32_t)) - O << MAI->getData32bitsDirective(); - else - O << MAI->getData64bitsDirective(); + if (Asm->VerboseAsm) Asm->OutStreamer.AddComment("DIE offset"); + Asm->EmitInt32(LI->second->getOffset()); - PrintLabelName("label", LI->first); EOL("low_pc"); + if (Asm->VerboseAsm) Asm->OutStreamer.AddComment("low_pc"); + Asm->OutStreamer.EmitSymbolValue(LI->first, TD->getPointerSize(), 0); } } - EmitLabel("debug_inlined_end", 1); - Asm->O << '\n'; + Asm->OutStreamer.EmitLabel(getDWLabel("debug_inlined_end", 1)); } diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.h b/lib/CodeGen/AsmPrinter/DwarfDebug.h index 55baa92..40d1d64 100644 --- a/lib/CodeGen/AsmPrinter/DwarfDebug.h +++ b/lib/CodeGen/AsmPrinter/DwarfDebug.h @@ -62,14 +62,6 @@ class DwarfDebug : public DwarfPrinter { // Attributes used to construct specific Dwarf sections. // - /// CompileUnitMap - A map of global variables representing compile units to - /// compile units. - DenseMap<Value *, CompileUnit *> CompileUnitMap; - - /// CompileUnits - All the compile units in this module. - /// - SmallVector<CompileUnit *, 8> CompileUnits; - /// ModuleCU - All DIEs are inserted in ModuleCU. CompileUnit *ModuleCU; @@ -175,8 +167,8 @@ class DwarfDebug : public DwarfPrinter { /// InlineInfo - Keep track of inlined functions and their location. This /// information is used to populate debug_inlined section. - typedef std::pair<unsigned, DIE *> InlineInfoLabels; - DenseMap<MDNode *, SmallVector<InlineInfoLabels, 4> > InlineInfo; + typedef std::pair<MCSymbol*, DIE *> InlineInfoLabels; + DenseMap<MDNode*, SmallVector<InlineInfoLabels, 4> > InlineInfo; SmallVector<MDNode *, 4> InlinedSPNodes; /// CompileUnitOffsets - A vector of the offsets of the compile units. This is @@ -251,23 +243,18 @@ class DwarfDebug : public DwarfPrinter { /// addLabel - Add a Dwarf label attribute data and value. /// void addLabel(DIE *Die, unsigned Attribute, unsigned Form, - const DWLabel &Label); - - /// addObjectLabel - Add an non-Dwarf label attribute data and value. - /// - void addObjectLabel(DIE *Die, unsigned Attribute, unsigned Form, - const MCSymbol *Sym); + const MCSymbol *Label); /// addSectionOffset - Add a section offset label attribute data and value. /// void addSectionOffset(DIE *Die, unsigned Attribute, unsigned Form, - const DWLabel &Label, const DWLabel &Section, - bool isEH = false, bool useSet = true); + const MCSymbol *Label, const MCSymbol *Section, + bool isEH = false); /// addDelta - Add a label delta attribute data and value. /// void addDelta(DIE *Die, unsigned Attribute, unsigned Form, - const DWLabel &Hi, const DWLabel &Lo); + const MCSymbol *Hi, const MCSymbol *Lo); /// addDIEEntry - Add a DIE attribute data and value. /// @@ -346,7 +333,7 @@ class DwarfDebug : public DwarfPrinter { DICompositeType *CTy); /// constructEnumTypeDIE - Construct enum type DIE from DIEnumerator. - DIE *constructEnumTypeDIE(DIEnumerator *ETy); + DIE *constructEnumTypeDIE(DIEnumerator ETy); /// createGlobalVariableDIE - Create new DIE using GV. DIE *createGlobalVariableDIE(const DIGlobalVariable &GV); @@ -357,10 +344,6 @@ class DwarfDebug : public DwarfPrinter { /// createSubprogramDIE - Create new DIE using SP. DIE *createSubprogramDIE(const DISubprogram &SP, bool MakeDecl = false); - /// findCompileUnit - Get the compile unit for the given descriptor. - /// - CompileUnit *findCompileUnit(DICompileUnit Unit); - /// getUpdatedDbgScope - Find or create DbgScope assicated with /// the instruction. Initialize scope and update scope hierarchy. DbgScope *getUpdatedDbgScope(MDNode *N, const MachineInstr *MI, MDNode *InlinedAt); @@ -529,10 +512,10 @@ public: /// void endFunction(const MachineFunction *MF); - /// recordSourceLine - Records location information and associates it with a - /// label. Returns a unique label ID used to generate a label and provide - /// correspondence to the source line list. - unsigned recordSourceLine(unsigned Line, unsigned Col, MDNode *Scope); + /// recordSourceLine - Register a source line with debug info. Returns the + /// unique label that was emitted and which provides correspondence to + /// the source line list. + MCSymbol *recordSourceLine(unsigned Line, unsigned Col, MDNode *Scope); /// getSourceLineCount - Return the number of source lines in the debug /// info. @@ -556,7 +539,7 @@ public: void collectVariableInfo(); /// beginScope - Process beginning of a scope starting at Label. - void beginScope(const MachineInstr *MI, unsigned Label); + void beginScope(const MachineInstr *MI, MCSymbol *Label); /// endScope - Prcess end of a scope. void endScope(const MachineInstr *MI); diff --git a/lib/CodeGen/AsmPrinter/DwarfException.cpp b/lib/CodeGen/AsmPrinter/DwarfException.cpp index 2b08ba4..11a01fe 100644 --- a/lib/CodeGen/AsmPrinter/DwarfException.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfException.cpp @@ -39,7 +39,7 @@ using namespace llvm; DwarfException::DwarfException(raw_ostream &OS, AsmPrinter *A, const MCAsmInfo *T) - : DwarfPrinter(OS, A, T, "eh"), shouldEmitTable(false),shouldEmitMoves(false), + : DwarfPrinter(OS, A, T), shouldEmitTable(false),shouldEmitMoves(false), shouldEmitTableModule(false), shouldEmitMovesModule(false), ExceptionTimer(0) { if (TimePassesIsEnabled) @@ -60,7 +60,7 @@ const MCExpr *DwarfException::CreateLabelDiff(const MCExpr *ExprRef, raw_svector_ostream(Name) << MAI->getPrivateGlobalPrefix() << LabelName << Asm->getFunctionNumber() << "_" << Index; - MCSymbol *DotSym = Asm->OutContext.GetOrCreateSymbol(Name.str()); + MCSymbol *DotSym = Asm->OutContext.GetOrCreateTemporarySymbol(Name.str()); Asm->OutStreamer.EmitLabel(DotSym); return MCBinaryExpr::CreateSub(ExprRef, @@ -84,25 +84,29 @@ void DwarfException::EmitCIE(const Function *PersonalityFn, unsigned Index) { // Begin eh frame section. Asm->OutStreamer.SwitchSection(TLOF.getEHFrameSection()); - if (MAI->is_EHSymbolPrivate()) - O << MAI->getPrivateGlobalPrefix(); - O << "EH_frame" << Index << ":\n"; + MCSymbol *EHFrameSym; + if (TLOF.isFunctionEHFrameSymbolPrivate()) + EHFrameSym = getDWLabel("EH_frame", Index); + else + EHFrameSym = Asm->OutContext.GetOrCreateSymbol(Twine("EH_frame") + + Twine(Index)); + Asm->OutStreamer.EmitLabel(EHFrameSym); - EmitLabel("section_eh_frame", Index); + Asm->OutStreamer.EmitLabel(getDWLabel("section_eh_frame", Index)); // Define base labels. - EmitLabel("eh_frame_common", Index); + Asm->OutStreamer.EmitLabel(getDWLabel("eh_frame_common", Index)); // Define the eh frame length. - EmitDifference("eh_frame_common_end", Index, - "eh_frame_common_begin", Index, true); - EOL("Length of Common Information Entry"); + Asm->OutStreamer.AddComment("Length of Common Information Entry"); + EmitDifference(getDWLabel("eh_frame_common_end", Index), + getDWLabel("eh_frame_common_begin", Index), true); // EH frame header. - EmitLabel("eh_frame_common_begin", Index); - if (Asm->VerboseAsm) Asm->OutStreamer.AddComment("CIE Identifier Tag"); + Asm->OutStreamer.EmitLabel(getDWLabel("eh_frame_common_begin", Index)); + Asm->OutStreamer.AddComment("CIE Identifier Tag"); Asm->OutStreamer.EmitIntValue(0, 4/*size*/, 0/*addrspace*/); - if (Asm->VerboseAsm) Asm->OutStreamer.AddComment("DW_CIE_VERSION"); + Asm->OutStreamer.AddComment("DW_CIE_VERSION"); Asm->OutStreamer.EmitIntValue(dwarf::DW_CIE_VERSION, 1/*size*/, 0/*addr*/); // The personality presence indicates that language specific information will @@ -138,14 +142,14 @@ void DwarfException::EmitCIE(const Function *PersonalityFn, unsigned Index) { if (APtr != Augmentation + 1) Augmentation[0] = 'z'; + Asm->OutStreamer.AddComment("CIE Augmentation"); Asm->OutStreamer.EmitBytes(StringRef(Augmentation, strlen(Augmentation)+1),0); - EOL("CIE Augmentation"); // Round out reader. EmitULEB128(1, "CIE Code Alignment Factor"); EmitSLEB128(stackGrowth, "CIE Data Alignment Factor"); + Asm->OutStreamer.AddComment("CIE Return Address Column"); Asm->EmitInt8(RI->getDwarfRegNum(RI->getRARegister(), true)); - EOL("CIE Return Address Column"); if (Augmentation[0]) { EmitULEB128(AugmentationSize, "Augmentation Size"); @@ -153,8 +157,8 @@ void DwarfException::EmitCIE(const Function *PersonalityFn, unsigned Index) { // If there is a personality, we need to indicate the function's location. if (PersonalityFn) { EmitEncodingByte(PerEncoding, "Personality"); + Asm->OutStreamer.AddComment("Personality"); EmitReference(PersonalityFn, PerEncoding); - EOL("Personality"); } if (UsesLSDA[Index]) EmitEncodingByte(LSDAEncoding, "LSDA"); @@ -171,8 +175,7 @@ void DwarfException::EmitCIE(const Function *PersonalityFn, unsigned Index) { // be 8-byte on 64-bit targets to match what gcc does. Otherwise you get // holes which confuse readers of eh_frame. Asm->EmitAlignment(TD->getPointerSize() == 4 ? 2 : 3, 0, 0, false); - EmitLabel("eh_frame_common_end", Index); - Asm->O << '\n'; + Asm->OutStreamer.EmitLabel(getDWLabel("eh_frame_common_end", Index)); } /// EmitFDE - Emit the Frame Description Entry (FDE) for the function. @@ -190,13 +193,13 @@ void DwarfException::EmitFDE(const FunctionEHFrameInfo &EHFrameInfo) { // Externally visible entry into the functions eh frame info. If the // corresponding function is static, this should not be externally visible. - if (!TheFunc->hasLocalLinkage()) - if (const char *GlobalEHDirective = MAI->getGlobalEHDirective()) - O << GlobalEHDirective << *EHFrameInfo.FunctionEHSym << '\n'; + if (!TheFunc->hasLocalLinkage() && TLOF.isFunctionEHSymbolGlobal()) + Asm->OutStreamer.EmitSymbolAttribute(EHFrameInfo.FunctionEHSym,MCSA_Global); // If corresponding function is weak definition, this should be too. if (TheFunc->isWeakForLinker() && MAI->getWeakDefDirective()) - O << MAI->getWeakDefDirective() << *EHFrameInfo.FunctionEHSym << '\n'; + Asm->OutStreamer.EmitSymbolAttribute(EHFrameInfo.FunctionEHSym, + MCSA_WeakDefinition); // If corresponding function is hidden, this should be too. if (TheFunc->hasHiddenVisibility()) @@ -211,8 +214,9 @@ void DwarfException::EmitFDE(const FunctionEHFrameInfo &EHFrameInfo) { if (!EHFrameInfo.hasCalls && !UnwindTablesMandatory && (!TheFunc->isWeakForLinker() || !MAI->getWeakDefDirective() || - MAI->getSupportsWeakOmittedEHFrame())) { - O << *EHFrameInfo.FunctionEHSym << " = 0\n"; + TLOF.getSupportsWeakOmittedEHFrame())) { + Asm->OutStreamer.EmitAssignment(EHFrameInfo.FunctionEHSym, + MCConstantExpr::Create(0, Asm->OutContext)); // This name has no connection to the function, so it might get // dead-stripped when the function is not, erroneously. Prohibit // dead-stripping unconditionally. @@ -220,28 +224,29 @@ void DwarfException::EmitFDE(const FunctionEHFrameInfo &EHFrameInfo) { Asm->OutStreamer.EmitSymbolAttribute(EHFrameInfo.FunctionEHSym, MCSA_NoDeadStrip); } else { - O << *EHFrameInfo.FunctionEHSym << ":\n"; + Asm->OutStreamer.EmitLabel(EHFrameInfo.FunctionEHSym); // EH frame header. - EmitDifference("eh_frame_end", EHFrameInfo.Number, - "eh_frame_begin", EHFrameInfo.Number, + Asm->OutStreamer.AddComment("Length of Frame Information Entry"); + EmitDifference(getDWLabel("eh_frame_end", EHFrameInfo.Number), + getDWLabel("eh_frame_begin", EHFrameInfo.Number), true); - EOL("Length of Frame Information Entry"); - EmitLabel("eh_frame_begin", EHFrameInfo.Number); + Asm->OutStreamer.EmitLabel(getDWLabel("eh_frame_begin",EHFrameInfo.Number)); - EmitSectionOffset("eh_frame_begin", "eh_frame_common", - EHFrameInfo.Number, EHFrameInfo.PersonalityIndex, - true, true, false); + Asm->OutStreamer.AddComment("FDE CIE offset"); + EmitSectionOffset(getDWLabel("eh_frame_begin", EHFrameInfo.Number), + getDWLabel("eh_frame_common", + EHFrameInfo.PersonalityIndex), + true, true); - EOL("FDE CIE offset"); - EmitReference("eh_func_begin", EHFrameInfo.Number, FDEEncoding); - EOL("FDE initial location"); - EmitDifference("eh_func_end", EHFrameInfo.Number, - "eh_func_begin", EHFrameInfo.Number, + Asm->OutStreamer.AddComment("FDE initial location"); + EmitReference(getDWLabel("eh_func_begin", EHFrameInfo.Number), FDEEncoding); + Asm->OutStreamer.AddComment("FDE address range"); + EmitDifference(getDWLabel("eh_func_end", EHFrameInfo.Number), + getDWLabel("eh_func_begin", EHFrameInfo.Number), SizeOfEncodedValue(FDEEncoding) == 4); - EOL("FDE address range"); // If there is a personality and landing pads then point to the language // specific data area in the exception table. @@ -249,12 +254,12 @@ void DwarfException::EmitFDE(const FunctionEHFrameInfo &EHFrameInfo) { unsigned Size = SizeOfEncodedValue(LSDAEncoding); EmitULEB128(Size, "Augmentation size"); + Asm->OutStreamer.AddComment("Language Specific Data Area"); if (EHFrameInfo.hasLandingPads) - EmitReference("exception", EHFrameInfo.Number, LSDAEncoding); + EmitReference(getDWLabel("exception", EHFrameInfo.Number),LSDAEncoding); else Asm->OutStreamer.EmitIntValue(0, Size/*size*/, 0/*addrspace*/); - EOL("Language Specific Data Area"); } else { EmitULEB128(0, "Augmentation size"); } @@ -268,7 +273,7 @@ void DwarfException::EmitFDE(const FunctionEHFrameInfo &EHFrameInfo) { // get holes which confuse readers of eh_frame. Asm->EmitAlignment(TD->getPointerSize() == sizeof(int32_t) ? 2 : 3, 0, 0, false); - EmitLabel("eh_frame_end", EHFrameInfo.Number); + Asm->OutStreamer.EmitLabel(getDWLabel("eh_frame_end", EHFrameInfo.Number)); // If the function is marked used, this table should be also. We cannot // make the mark unconditional in this case, since retaining the table also @@ -280,7 +285,7 @@ void DwarfException::EmitFDE(const FunctionEHFrameInfo &EHFrameInfo) { Asm->OutStreamer.EmitSymbolAttribute(EHFrameInfo.FunctionEHSym, MCSA_NoDeadStrip); } - Asm->O << '\n'; + Asm->OutStreamer.AddBlankLine(); } /// SharedTypeIds - How many leading type ids two landing pads have in common. @@ -699,15 +704,14 @@ void DwarfException::EmitExceptionTable() { Asm->EmitAlignment(2, 0, 0, false); // Emit the LSDA. - O << "GCC_except_table" << SubprogramCount << ":\n"; - EmitLabel("exception", SubprogramCount); + MCSymbol *GCCETSym = + Asm->OutContext.GetOrCreateSymbol(Twine("GCC_except_table")+ + Twine(SubprogramCount)); + Asm->OutStreamer.EmitLabel(GCCETSym); + Asm->OutStreamer.EmitLabel(getDWLabel("exception", SubprogramCount)); - if (IsSJLJ) { - SmallString<16> LSDAName; - raw_svector_ostream(LSDAName) << MAI->getPrivateGlobalPrefix() << - "_LSDA_" << Asm->getFunctionNumber(); - O << LSDAName.str() << ":\n"; - } + if (IsSJLJ) + Asm->OutStreamer.EmitLabel(getDWLabel("_LSDA_", Asm->getFunctionNumber())); // Emit the LSDA header. EmitEncodingByte(dwarf::DW_EH_PE_omit, "@LPStart"); @@ -819,27 +823,30 @@ void DwarfException::EmitExceptionTable() { // Offset of the call site relative to the previous call site, counted in // number of 16-byte bundles. The first call site is counted relative to // the start of the procedure fragment. - EmitSectionOffset(BeginTag, "eh_func_begin", BeginNumber, SubprogramCount, + Asm->OutStreamer.AddComment("Region start"); + EmitSectionOffset(getDWLabel(BeginTag, BeginNumber), + getDWLabel("eh_func_begin", SubprogramCount), true, true); - EOL("Region start"); + Asm->OutStreamer.AddComment("Region length"); if (!S.EndLabel) - EmitDifference("eh_func_end", SubprogramCount, BeginTag, BeginNumber, + EmitDifference(getDWLabel("eh_func_end", SubprogramCount), + getDWLabel(BeginTag, BeginNumber), true); else - EmitDifference("label", S.EndLabel, BeginTag, BeginNumber, true); + EmitDifference(getDWLabel("label", S.EndLabel), + getDWLabel(BeginTag, BeginNumber), true); - EOL("Region length"); // Offset of the landing pad, counted in 16-byte bundles relative to the // @LPStart address. + Asm->OutStreamer.AddComment("Landing pad"); if (!S.PadLabel) { - Asm->OutStreamer.AddComment("Landing pad"); Asm->OutStreamer.EmitIntValue(0, 4/*size*/, 0/*addrspace*/); } else { - EmitSectionOffset("label", "eh_func_begin", S.PadLabel, SubprogramCount, + EmitSectionOffset(getDWLabel("label", S.PadLabel), + getDWLabel("eh_func_begin", SubprogramCount), true, true); - EOL("Landing pad"); } // Offset of the first associated action record, relative to the start of @@ -850,11 +857,16 @@ void DwarfException::EmitExceptionTable() { } // Emit the Action Table. - if (Actions.size() != 0) EOL("-- Action Record Table --"); + if (Actions.size() != 0) { + Asm->OutStreamer.AddComment("-- Action Record Table --"); + Asm->OutStreamer.AddBlankLine(); + } + for (SmallVectorImpl<ActionEntry>::const_iterator I = Actions.begin(), E = Actions.end(); I != E; ++I) { const ActionEntry &Action = *I; - EOL("Action Record:"); + Asm->OutStreamer.AddComment("Action Record"); + Asm->OutStreamer.AddBlankLine(); // Type Filter // @@ -870,23 +882,26 @@ void DwarfException::EmitExceptionTable() { } // Emit the Catch TypeInfos. - if (!TypeInfos.empty()) EOL("-- Catch TypeInfos --"); + if (!TypeInfos.empty()) { + Asm->OutStreamer.AddComment("-- Catch TypeInfos --"); + Asm->OutStreamer.AddBlankLine(); + } for (std::vector<GlobalVariable *>::const_reverse_iterator I = TypeInfos.rbegin(), E = TypeInfos.rend(); I != E; ++I) { const GlobalVariable *GV = *I; - if (GV) { + Asm->OutStreamer.AddComment("TypeInfo"); + if (GV) EmitReference(GV, TTypeEncoding); - EOL("TypeInfo"); - } else { - PrintRelDirective(TTypeEncoding); - O << "0x0"; - EOL(""); - } + else + Asm->OutStreamer.EmitIntValue(0, SizeOfEncodedValue(TTypeEncoding), 0); } // Emit the Exception Specifications. - if (!FilterIds.empty()) EOL("-- Filter IDs --"); + if (!FilterIds.empty()) { + Asm->OutStreamer.AddComment("-- Filter IDs --"); + Asm->OutStreamer.AddBlankLine(); + } for (std::vector<unsigned>::const_iterator I = FilterIds.begin(), E = FilterIds.end(); I < E; ++I) { unsigned TypeID = *I; @@ -945,7 +960,7 @@ void DwarfException::BeginFunction(const MachineFunction *MF) { if (shouldEmitMoves || shouldEmitTable) // Assumes in correct section after the entry point. - EmitLabel("eh_func_begin", ++SubprogramCount); + Asm->OutStreamer.EmitLabel(getDWLabel("eh_func_begin", ++SubprogramCount)); shouldEmitTableModule |= shouldEmitTable; shouldEmitMovesModule |= shouldEmitMoves; @@ -962,12 +977,13 @@ void DwarfException::EndFunction() { if (TimePassesIsEnabled) ExceptionTimer->startTimer(); - EmitLabel("eh_func_end", SubprogramCount); + Asm->OutStreamer.EmitLabel(getDWLabel("eh_func_end", SubprogramCount)); EmitExceptionTable(); + const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering(); MCSymbol *FunctionEHSym = Asm->GetSymbolWithGlobalValueBase(MF->getFunction(), ".eh", - Asm->MAI->is_EHSymbolPrivate()); + TLOF.isFunctionEHFrameSymbolPrivate()); // Save EH frame information EHFrames.push_back(FunctionEHFrameInfo(FunctionEHSym, SubprogramCount, diff --git a/lib/CodeGen/AsmPrinter/DwarfLabel.cpp b/lib/CodeGen/AsmPrinter/DwarfLabel.cpp deleted file mode 100644 index 6e9293a..0000000 --- a/lib/CodeGen/AsmPrinter/DwarfLabel.cpp +++ /dev/null @@ -1,32 +0,0 @@ -//===--- lib/CodeGen/DwarfLabel.cpp - Dwarf Label -------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// DWARF Labels -// -//===----------------------------------------------------------------------===// - -#include "DwarfLabel.h" -#include "llvm/ADT/FoldingSet.h" -#include "llvm/Support/raw_ostream.h" - -using namespace llvm; - -/// Profile - Used to gather unique data for the folding set. -/// -void DWLabel::Profile(FoldingSetNodeID &ID) const { - ID.AddString(Tag); - ID.AddInteger(Number); -} - -#ifndef NDEBUG -void DWLabel::print(raw_ostream &O) const { - O << "." << Tag; - if (Number) O << Number; -} -#endif diff --git a/lib/CodeGen/AsmPrinter/DwarfLabel.h b/lib/CodeGen/AsmPrinter/DwarfLabel.h deleted file mode 100644 index 0c0cc4b..0000000 --- a/lib/CodeGen/AsmPrinter/DwarfLabel.h +++ /dev/null @@ -1,52 +0,0 @@ -//===--- lib/CodeGen/DwarfLabel.h - Dwarf Label -----------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// DWARF Labels. -// -//===----------------------------------------------------------------------===// - -#ifndef CODEGEN_ASMPRINTER_DWARFLABEL_H__ -#define CODEGEN_ASMPRINTER_DWARFLABEL_H__ - -namespace llvm { - class FoldingSetNodeID; - class raw_ostream; - - //===--------------------------------------------------------------------===// - /// DWLabel - Labels are used to track locations in the assembler file. - /// Labels appear in the form @verbatim <prefix><Tag><Number> @endverbatim, - /// where the tag is a category of label (Ex. location) and number is a value - /// unique in that category. - class DWLabel { - /// Tag - Label category tag. Should always be a statically declared C - /// string. - /// - const char *Tag; - - /// Number - Value to make label unique. - /// - unsigned Number; - public: - DWLabel(const char *T, unsigned N) : Tag(T), Number(N) {} - - // Accessors. - const char *getTag() const { return Tag; } - unsigned getNumber() const { return Number; } - - /// Profile - Used to gather unique data for the folding set. - /// - void Profile(FoldingSetNodeID &ID) const; - -#ifndef NDEBUG - void print(raw_ostream &O) const; -#endif - }; -} // end llvm namespace - -#endif diff --git a/lib/CodeGen/AsmPrinter/DwarfPrinter.cpp b/lib/CodeGen/AsmPrinter/DwarfPrinter.cpp index 28ff0eb..7890e5c 100644 --- a/lib/CodeGen/AsmPrinter/DwarfPrinter.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfPrinter.cpp @@ -31,11 +31,31 @@ #include "llvm/ADT/SmallString.h" using namespace llvm; -DwarfPrinter::DwarfPrinter(raw_ostream &OS, AsmPrinter *A, const MCAsmInfo *T, - const char *flavor) +DwarfPrinter::DwarfPrinter(raw_ostream &OS, AsmPrinter *A, const MCAsmInfo *T) : O(OS), Asm(A), MAI(T), TD(Asm->TM.getTargetData()), RI(Asm->TM.getRegisterInfo()), M(NULL), MF(NULL), MMI(NULL), - SubprogramCount(0), Flavor(flavor), SetCounter(1) {} + SubprogramCount(0) {} + + +/// getDWLabel - Return the MCSymbol corresponding to the assembler temporary +/// label with the specified stem and unique ID. +MCSymbol *DwarfPrinter::getDWLabel(const char *Name, unsigned ID) const { + // FIXME: REMOVE this. However, there is stuff in EH that passes counters in + // here that can be zero. + + //assert(ID && "Should use getTempLabel if no ID"); + if (ID == 0) return getTempLabel(Name); + return Asm->OutContext.GetOrCreateTemporarySymbol + (Twine(MAI->getPrivateGlobalPrefix()) + Twine(Name) + Twine(ID)); +} + +/// getTempLabel - Return the MCSymbol corresponding to the assembler temporary +/// label with the specified name. +MCSymbol *DwarfPrinter::getTempLabel(const char *Name) const { + return Asm->OutContext.GetOrCreateTemporarySymbol + (Twine(MAI->getPrivateGlobalPrefix()) + Name); +} + /// SizeOfEncodedValue - Return the size of the encoding in bytes. unsigned DwarfPrinter::SizeOfEncodedValue(unsigned Encoding) const { @@ -57,33 +77,6 @@ unsigned DwarfPrinter::SizeOfEncodedValue(unsigned Encoding) const { return 0; } -void DwarfPrinter::PrintRelDirective(bool Force32Bit, bool isInSection) const { - if (isInSection && MAI->getDwarfSectionOffsetDirective()) - O << MAI->getDwarfSectionOffsetDirective(); - else if (Force32Bit || TD->getPointerSize() == sizeof(int32_t)) - O << MAI->getData32bitsDirective(); - else - O << MAI->getData64bitsDirective(); -} - -void DwarfPrinter::PrintRelDirective(unsigned Encoding) const { - unsigned Size = SizeOfEncodedValue(Encoding); - assert((Size == 4 || Size == 8) && "Do not support other types or rels!"); - - O << (Size == 4 ? - MAI->getData32bitsDirective() : MAI->getData64bitsDirective()); -} - -/// EOL - Print a newline character to asm stream. If a comment is present -/// then it will be printed first. Comments should not contain '\n'. -void DwarfPrinter::EOL(const Twine &Comment) const { - if (Asm->VerboseAsm && !Comment.isTriviallyEmpty()) { - Asm->O.PadToColumn(MAI->getCommentColumn()); - Asm->O << Asm->MAI->getCommentString() << ' ' << Comment; - } - Asm->O << '\n'; -} - static const char *DecodeDWARFEncoding(unsigned Encoding) { switch (Encoding) { case dwarf::DW_EH_PE_absptr: return "absptr"; @@ -145,6 +138,7 @@ void DwarfPrinter::EmitSLEB128(int Value, const char *Desc) const { Asm->OutStreamer.AddComment(Desc); if (MAI->hasLEB128()) { + // FIXME: MCize. O << "\t.sleb128\t" << Value; Asm->OutStreamer.AddBlankLine(); return; @@ -170,6 +164,7 @@ void DwarfPrinter::EmitULEB128(unsigned Value, const char *Desc, Asm->OutStreamer.AddComment(Desc); if (MAI->hasLEB128() && PadTo == 0) { + // FIXME: MCize. O << "\t.uleb128\t" << Value; Asm->OutStreamer.AddBlankLine(); return; @@ -191,134 +186,48 @@ void DwarfPrinter::EmitULEB128(unsigned Value, const char *Desc, } -/// PrintLabelName - Print label name in form used by Dwarf writer. -/// -void DwarfPrinter::PrintLabelName(const char *Tag, unsigned Number) const { - O << MAI->getPrivateGlobalPrefix() << Tag; - if (Number) O << Number; -} -void DwarfPrinter::PrintLabelName(const char *Tag, unsigned Number, - const char *Suffix) const { - O << MAI->getPrivateGlobalPrefix() << Tag; - if (Number) O << Number; - O << Suffix; -} - -/// EmitLabel - Emit location label for internal use by Dwarf. -/// -void DwarfPrinter::EmitLabel(const char *Tag, unsigned Number) const { - PrintLabelName(Tag, Number); - O << ":\n"; -} - -/// EmitReference - Emit a reference to a label. -/// -void DwarfPrinter::EmitReference(const char *Tag, unsigned Number, - bool IsPCRelative, bool Force32Bit) const { - PrintRelDirective(Force32Bit); - PrintLabelName(Tag, Number); - if (IsPCRelative) O << "-" << MAI->getPCSymbol(); -} -void DwarfPrinter::EmitReference(const std::string &Name, bool IsPCRelative, - bool Force32Bit) const { - PrintRelDirective(Force32Bit); - O << Name; - if (IsPCRelative) O << "-" << MAI->getPCSymbol(); -} - -void DwarfPrinter::EmitReference(const MCSymbol *Sym, bool IsPCRelative, - bool Force32Bit) const { - PrintRelDirective(Force32Bit); - O << *Sym; - if (IsPCRelative) O << "-" << MAI->getPCSymbol(); -} - -void DwarfPrinter::EmitReference(const char *Tag, unsigned Number, - unsigned Encoding) const { - SmallString<64> Name; - raw_svector_ostream(Name) << MAI->getPrivateGlobalPrefix() - << Tag << Number; - - MCSymbol *Sym = Asm->OutContext.GetOrCreateSymbol(Name.str()); - EmitReference(Sym, Encoding); -} - void DwarfPrinter::EmitReference(const MCSymbol *Sym, unsigned Encoding) const { const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering(); - PrintRelDirective(Encoding); - O << *TLOF.getSymbolForDwarfReference(Sym, Asm->MMI, Encoding);; + const MCExpr *Exp = TLOF.getSymbolForDwarfReference(Sym, Asm->MMI, Encoding); + Asm->OutStreamer.EmitValue(Exp, SizeOfEncodedValue(Encoding), /*addrspace*/0); } -void DwarfPrinter::EmitReference(const GlobalValue *GV, unsigned Encoding)const { +void DwarfPrinter::EmitReference(const GlobalValue *GV, unsigned Encoding)const{ const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering(); - PrintRelDirective(Encoding); - O << *TLOF.getSymbolForDwarfGlobalReference(GV, Asm->Mang, - Asm->MMI, Encoding);; + const MCExpr *Exp = + TLOF.getSymbolForDwarfGlobalReference(GV, Asm->Mang, Asm->MMI, Encoding); + Asm->OutStreamer.EmitValue(Exp, SizeOfEncodedValue(Encoding), /*addrspace*/0); } /// EmitDifference - Emit the difference between two labels. If this assembler /// supports .set, we emit a .set of a temporary and then use it in the .word. -void DwarfPrinter::EmitDifference(const char *TagHi, unsigned NumberHi, - const char *TagLo, unsigned NumberLo, +void DwarfPrinter::EmitDifference(const MCSymbol *TagHi, const MCSymbol *TagLo, bool IsSmall) { - if (MAI->hasSetDirective()) { - // FIXME: switch to OutStreamer.EmitAssignment. - O << "\t.set\t"; - PrintLabelName("set", SetCounter, Flavor); - O << ","; - PrintLabelName(TagHi, NumberHi); - O << "-"; - PrintLabelName(TagLo, NumberLo); - O << "\n"; - - PrintRelDirective(IsSmall); - PrintLabelName("set", SetCounter, Flavor); - ++SetCounter; - } else { - PrintRelDirective(IsSmall); - PrintLabelName(TagHi, NumberHi); - O << "-"; - PrintLabelName(TagLo, NumberLo); - } + unsigned Size = IsSmall ? 4 : TD->getPointerSize(); + Asm->EmitLabelDifference(TagHi, TagLo, Size); } -void DwarfPrinter::EmitSectionOffset(const char* Label, const char* Section, - unsigned LabelNumber, - unsigned SectionNumber, - bool IsSmall, bool isEH, - bool useSet) { - bool printAbsolute = false; +void DwarfPrinter::EmitSectionOffset(const MCSymbol *Label, + const MCSymbol *Section, + bool IsSmall, bool isEH) { + bool isAbsolute; if (isEH) - printAbsolute = MAI->isAbsoluteEHSectionOffsets(); + isAbsolute = MAI->isAbsoluteEHSectionOffsets(); else - printAbsolute = MAI->isAbsoluteDebugSectionOffsets(); - - if (MAI->hasSetDirective() && useSet) { - // FIXME: switch to OutStreamer.EmitAssignment. - O << "\t.set\t"; - PrintLabelName("set", SetCounter, Flavor); - O << ","; - PrintLabelName(Label, LabelNumber); - - if (!printAbsolute) { - O << "-"; - PrintLabelName(Section, SectionNumber); - } + isAbsolute = MAI->isAbsoluteDebugSectionOffsets(); - O << "\n"; - PrintRelDirective(IsSmall); - PrintLabelName("set", SetCounter, Flavor); - ++SetCounter; - } else { - PrintRelDirective(IsSmall, true); - PrintLabelName(Label, LabelNumber); - - if (!printAbsolute) { - O << "-"; - PrintLabelName(Section, SectionNumber); - } + if (!isAbsolute) + return EmitDifference(Label, Section, IsSmall); + + // On COFF targets, we have to emit the weird .secrel32 directive. + if (const char *SecOffDir = MAI->getDwarfSectionOffsetDirective()) + // FIXME: MCize. + Asm->O << SecOffDir << Label->getName(); + else { + unsigned Size = IsSmall ? 4 : TD->getPointerSize(); + Asm->OutStreamer.EmitSymbolValue(Label, Size, 0/*AddrSpace*/); } } @@ -337,12 +246,9 @@ void DwarfPrinter::EmitFrameMoves(const char *BaseLabel, unsigned BaseLabelID, const MachineMove &Move = Moves[i]; unsigned LabelID = Move.getLabelID(); - if (LabelID) { - LabelID = MMI->MappedLabel(LabelID); - - // Throw out move if the label is invalid. - if (!LabelID) continue; - } + // Throw out move if the label is invalid. + if (LabelID && MMI->isLabelDeleted(LabelID)) + continue; const MachineLocation &Dst = Move.getDestination(); const MachineLocation &Src = Move.getSource(); @@ -350,9 +256,8 @@ void DwarfPrinter::EmitFrameMoves(const char *BaseLabel, unsigned BaseLabelID, // Advance row if new location. if (BaseLabel && LabelID && (BaseLabelID != LabelID || !IsLocal)) { EmitCFAByte(dwarf::DW_CFA_advance_loc4); - EmitDifference("label", LabelID, BaseLabel, BaseLabelID, true); - Asm->O << '\n'; - + EmitDifference(getDWLabel("label", LabelID), + getDWLabel(BaseLabel, BaseLabelID), true); BaseLabelID = LabelID; BaseLabel = "label"; IsLocal = true; diff --git a/lib/CodeGen/AsmPrinter/DwarfPrinter.h b/lib/CodeGen/AsmPrinter/DwarfPrinter.h index bd715f2..5e2d806 100644 --- a/lib/CodeGen/AsmPrinter/DwarfPrinter.h +++ b/lib/CodeGen/AsmPrinter/DwarfPrinter.h @@ -14,7 +14,6 @@ #ifndef CODEGEN_ASMPRINTER_DWARFPRINTER_H__ #define CODEGEN_ASMPRINTER_DWARFPRINTER_H__ -#include "DwarfLabel.h" #include "llvm/CodeGen/MachineLocation.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/FormattedStream.h" @@ -67,15 +66,7 @@ protected: /// SubprogramCount - The running count of functions being compiled. unsigned SubprogramCount; - /// Flavor - A unique string indicating what dwarf producer this is, used to - /// unique labels. - const char * const Flavor; - - /// SetCounter - A unique number for each '.set' directive. - unsigned SetCounter; - - DwarfPrinter(raw_ostream &OS, AsmPrinter *A, const MCAsmInfo *T, - const char *flavor); + DwarfPrinter(raw_ostream &OS, AsmPrinter *A, const MCAsmInfo *T); public: //===------------------------------------------------------------------===// @@ -86,17 +77,17 @@ public: const MCAsmInfo *getMCAsmInfo() const { return MAI; } const TargetData *getTargetData() const { return TD; } + /// getDWLabel - Return the MCSymbol corresponding to the assembler temporary + /// label with the specified stem and unique ID. + MCSymbol *getDWLabel(const char *Name, unsigned ID) const; + + /// getTempLabel - Return an assembler temporary label with the specified + /// name. + MCSymbol *getTempLabel(const char *Name) const; + /// SizeOfEncodedValue - Return the size of the encoding in bytes. unsigned SizeOfEncodedValue(unsigned Encoding) const; - void PrintRelDirective(unsigned Encoding) const; - void PrintRelDirective(bool Force32Bit = false, - bool isInSection = false) const; - - /// EOL - Print a newline character to asm stream. If a comment is present - /// then it will be printed first. Comments should not contain '\n'. - void EOL(const Twine &Comment) const; - /// EmitEncodingByte - Emit a .byte 42 directive that corresponds to an /// encoding. If verbose assembly output is enabled, we output comments /// describing the encoding. Desc is a string saying what the encoding is @@ -115,57 +106,20 @@ public: unsigned PadTo = 0) const; - /// PrintLabelName - Print label name in form used by Dwarf writer. - /// - void PrintLabelName(const DWLabel &Label) const { - PrintLabelName(Label.getTag(), Label.getNumber()); - } - void PrintLabelName(const char *Tag, unsigned Number) const; - void PrintLabelName(const char *Tag, unsigned Number, - const char *Suffix) const; - - /// EmitLabel - Emit location label for internal use by Dwarf. - /// - void EmitLabel(const DWLabel &Label) const { - EmitLabel(Label.getTag(), Label.getNumber()); - } - void EmitLabel(const char *Tag, unsigned Number) const; - /// EmitReference - Emit a reference to a label. /// - void EmitReference(const DWLabel &Label, bool IsPCRelative = false, - bool Force32Bit = false) const { - EmitReference(Label.getTag(), Label.getNumber(), - IsPCRelative, Force32Bit); - } - void EmitReference(const char *Tag, unsigned Number, - bool IsPCRelative = false, - bool Force32Bit = false) const; - void EmitReference(const std::string &Name, bool IsPCRelative = false, - bool Force32Bit = false) const; - void EmitReference(const MCSymbol *Sym, bool IsPCRelative = false, - bool Force32Bit = false) const; - - void EmitReference(const char *Tag, unsigned Number, unsigned Encoding) const; void EmitReference(const MCSymbol *Sym, unsigned Encoding) const; void EmitReference(const GlobalValue *GV, unsigned Encoding) const; /// EmitDifference - Emit the difference between two labels. - void EmitDifference(const DWLabel &LabelHi, const DWLabel &LabelLo, - bool IsSmall = false) { - EmitDifference(LabelHi.getTag(), LabelHi.getNumber(), - LabelLo.getTag(), LabelLo.getNumber(), - IsSmall); - } - void EmitDifference(const char *TagHi, unsigned NumberHi, - const char *TagLo, unsigned NumberLo, + void EmitDifference(const MCSymbol *LabelHi, const MCSymbol *LabelLo, bool IsSmall = false); - void EmitSectionOffset(const char* Label, const char* Section, - unsigned LabelNumber, unsigned SectionNumber, - bool IsSmall = false, bool isEH = false, - bool useSet = true); - + /// EmitSectionOffset - Emit Label-Section or use a special purpose directive + /// to emit a section offset if the target has one. + void EmitSectionOffset(const MCSymbol *Label, const MCSymbol *Section, + bool IsSmall = false, bool isEH = false); + /// EmitFrameMoves - Emit frame instructions to describe the layout of the /// frame. void EmitFrameMoves(const char *BaseLabel, unsigned BaseLabelID, diff --git a/lib/CodeGen/AsmPrinter/DwarfWriter.cpp b/lib/CodeGen/AsmPrinter/DwarfWriter.cpp index 08e1bbc..9fd4c44 100644 --- a/lib/CodeGen/AsmPrinter/DwarfWriter.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfWriter.cpp @@ -73,11 +73,11 @@ void DwarfWriter::EndFunction(const MachineFunction *MF) { MMI->EndFunction(); } -/// RecordSourceLine - Records location information and associates it with a -/// label. Returns a unique label ID used to generate a label and provide -/// correspondence to the source line list. -unsigned DwarfWriter::RecordSourceLine(unsigned Line, unsigned Col, - MDNode *Scope) { +/// RecordSourceLine - Register a source line with debug info. Returns the +/// unique label that was emitted and which provides correspondence to +/// the source line list. +MCSymbol *DwarfWriter::RecordSourceLine(unsigned Line, unsigned Col, + MDNode *Scope) { return DD->recordSourceLine(Line, Col, Scope); } @@ -92,7 +92,7 @@ bool DwarfWriter::ShouldEmitDwarfDebug() const { return DD && DD->ShouldEmitDwarfDebug(); } -void DwarfWriter::BeginScope(const MachineInstr *MI, unsigned L) { +void DwarfWriter::BeginScope(const MachineInstr *MI, MCSymbol *L) { DD->beginScope(MI, L); } void DwarfWriter::EndScope(const MachineInstr *MI) { diff --git a/lib/CodeGen/BranchFolding.cpp b/lib/CodeGen/BranchFolding.cpp index d94729a..889763a 100644 --- a/lib/CodeGen/BranchFolding.cpp +++ b/lib/CodeGen/BranchFolding.cpp @@ -310,12 +310,23 @@ static unsigned HashEndOfMBB(const MachineBasicBlock *MBB, return 0; // Empty MBB. --I; + // Skip debug info so it will not affect codegen. + while (I->isDebugValue()) { + if (I==MBB->begin()) + return 0; // MBB empty except for debug info. + --I; + } unsigned Hash = HashMachineInstr(I); if (I == MBB->begin() || minCommonTailLength == 1) return Hash; // Single instr MBB. --I; + while (I->isDebugValue()) { + if (I==MBB->begin()) + return Hash; // MBB with single non-debug instr. + --I; + } // Hash in the second-to-last instruction. Hash ^= HashMachineInstr(I) << 2; return Hash; @@ -334,9 +345,32 @@ static unsigned ComputeCommonTailLength(MachineBasicBlock *MBB1, unsigned TailLen = 0; while (I1 != MBB1->begin() && I2 != MBB2->begin()) { --I1; --I2; - // Don't merge debugging pseudos. - if (I1->isDebugValue() || I2->isDebugValue() || - !I1->isIdenticalTo(I2) || + // Skip debugging pseudos; necessary to avoid changing the code. + while (I1->isDebugValue()) { + if (I1==MBB1->begin()) { + while (I2->isDebugValue()) { + if (I2==MBB2->begin()) + // I1==DBG at begin; I2==DBG at begin + return TailLen; + --I2; + } + ++I2; + // I1==DBG at begin; I2==non-DBG, or first of DBGs not at begin + return TailLen; + } + --I1; + } + // I1==first (untested) non-DBG preceding known match + while (I2->isDebugValue()) { + if (I2==MBB2->begin()) { + ++I1; + // I1==non-DBG, or first of DBGs not at begin; I2==DBG at begin + return TailLen; + } + --I2; + } + // I1, I2==first (untested) non-DBGs preceding known match + if (!I1->isIdenticalTo(I2) || // FIXME: This check is dubious. It's used to get around a problem where // people incorrectly expect inline asm directives to remain in the same // relative order. This is untenable because normal compiler @@ -348,6 +382,29 @@ static unsigned ComputeCommonTailLength(MachineBasicBlock *MBB1, } ++TailLen; } + // Back past possible debugging pseudos at beginning of block. This matters + // when one block differs from the other only by whether debugging pseudos + // are present at the beginning. (This way, the various checks later for + // I1==MBB1->begin() work as expected.) + if (I1 == MBB1->begin() && I2 != MBB2->begin()) { + --I2; + while (I2->isDebugValue()) { + if (I2 == MBB2->begin()) { + return TailLen; + } + --I2; + } + ++I2; + } + if (I2 == MBB2->begin() && I1 != MBB1->begin()) { + --I1; + while (I1->isDebugValue()) { + if (I1 == MBB1->begin()) + return TailLen; + --I1; + } + ++I1; + } return TailLen; } @@ -643,6 +700,8 @@ unsigned BranchFolder::CreateCommonTailOnlyBlock(MachineBasicBlock *&PredBB, SameTails[commonTailIndex].getTailStartPos(); MachineBasicBlock *MBB = SameTails[commonTailIndex].getBlock(); + // If the common tail includes any debug info we will take it pretty + // randomly from one of the inputs. Might be better to remove it? DEBUG(dbgs() << "\nSplitting BB#" << MBB->getNumber() << ", size " << maxCommonTailLength); @@ -912,6 +971,18 @@ bool BranchFolder::OptimizeBranches(MachineFunction &MF) { return MadeChange; } +// Blocks should be considered empty if they contain only debug info; +// else the debug info would affect codegen. +static bool IsEmptyBlock(MachineBasicBlock *MBB) { + if (MBB->empty()) + return true; + for (MachineBasicBlock::iterator MBBI = MBB->begin(), MBBE = MBB->end(); + MBBI!=MBBE; ++MBBI) { + if (!MBBI->isDebugValue()) + return false; + } + return true; +} /// IsBetterFallthrough - Return true if it would be clearly better to /// fall-through to MBB1 than to fall through into MBB2. This has to return @@ -949,7 +1020,7 @@ ReoptimizeBlock: // explicitly. Landing pads should not do this since the landing-pad table // points to this block. Blocks with their addresses taken shouldn't be // optimized away. - if (MBB->empty() && !MBB->isLandingPad() && !MBB->hasAddressTaken()) { + if (IsEmptyBlock(MBB) && !MBB->isLandingPad() && !MBB->hasAddressTaken()) { // Dead block? Leave for cleanup later. if (MBB->pred_empty()) return MadeChange; @@ -1141,7 +1212,23 @@ ReoptimizeBlock: // be 'non-branch terminators' in the block, try removing the branch and // then seeing if the block is empty. TII->RemoveBranch(*MBB); - + // If the only things remaining in the block are debug info, remove these + // as well, so this will behave the same as an empty block in non-debug + // mode. + if (!MBB->empty()) { + bool NonDebugInfoFound = false; + for (MachineBasicBlock::iterator I = MBB->begin(), E = MBB->end(); + I != E; ++I) { + if (!I->isDebugValue()) { + NonDebugInfoFound = true; + break; + } + } + if (!NonDebugInfoFound) + // Make the block empty, losing the debug info (we could probably + // improve this in some cases.) + MBB->erase(MBB->begin(), MBB->end()); + } // If this block is just an unconditional branch to CurTBB, we can // usually completely eliminate the block. The only case we cannot // completely eliminate the block is when the block before this one diff --git a/lib/CodeGen/LLVMTargetMachine.cpp b/lib/CodeGen/LLVMTargetMachine.cpp index 5e88865..9bc0b71 100644 --- a/lib/CodeGen/LLVMTargetMachine.cpp +++ b/lib/CodeGen/LLVMTargetMachine.cpp @@ -67,9 +67,6 @@ static cl::opt<bool> VerifyMachineCode("verify-machineinstrs", cl::Hidden, cl::desc("Verify generated machine code"), cl::init(getenv("LLVM_VERIFY_MACHINEINSTRS")!=NULL)); -static cl::opt<bool> EnableMachineCSE("enable-machine-cse", cl::Hidden, - cl::desc("Enable Machine CSE")); - static cl::opt<cl::boolOrDefault> AsmVerbose("asm-verbose", cl::desc("Add comments to directives."), cl::init(cl::BOU_UNSET)); @@ -328,11 +325,10 @@ bool LLVMTargetMachine::addCommonCodeGenPasses(PassManagerBase &PM, PM.add(createOptimizeExtsPass()); if (!DisableMachineLICM) PM.add(createMachineLICMPass()); - if (EnableMachineCSE) - PM.add(createMachineCSEPass()); + PM.add(createMachineCSEPass()); if (!DisableMachineSink) PM.add(createMachineSinkingPass()); - printAndVerify(PM, "After MachineLICM and MachineSinking", + printAndVerify(PM, "After Machine LICM, CSE and Sinking passes", /* allowDoubleDefs= */ true); } diff --git a/lib/CodeGen/LiveIntervalAnalysis.cpp b/lib/CodeGen/LiveIntervalAnalysis.cpp index ccda66f..f8b1707 100644 --- a/lib/CodeGen/LiveIntervalAnalysis.cpp +++ b/lib/CodeGen/LiveIntervalAnalysis.cpp @@ -593,13 +593,10 @@ void LiveIntervals::handleLiveInRegister(MachineBasicBlock *MBB, MachineBasicBlock::iterator E = MBB->end(); while (mi != E) { - if (mi->isDebugValue()) { + while (mi != E && mi->isDebugValue()) ++mi; - if (mi != E && !mi->isDebugValue()) { - baseIndex = indexes_->getNextNonNullIndex(baseIndex); - } - continue; - } + if (mi == E) + break; if (mi->killsRegister(interval.reg, tri_)) { DEBUG(dbgs() << " killed"); end = baseIndex.getDefIndex(); diff --git a/lib/CodeGen/MachineBasicBlock.cpp b/lib/CodeGen/MachineBasicBlock.cpp index 64134ce..32b1a7d 100644 --- a/lib/CodeGen/MachineBasicBlock.cpp +++ b/lib/CodeGen/MachineBasicBlock.cpp @@ -42,12 +42,11 @@ MachineBasicBlock::~MachineBasicBlock() { /// getSymbol - Return the MCSymbol for this basic block. /// MCSymbol *MachineBasicBlock::getSymbol(MCContext &Ctx) const { - SmallString<60> Name; const MachineFunction *MF = getParent(); - raw_svector_ostream(Name) - << MF->getTarget().getMCAsmInfo()->getPrivateGlobalPrefix() << "BB" - << MF->getFunctionNumber() << '_' << getNumber(); - return Ctx.GetOrCreateSymbol(Name.str()); + const char *Prefix = MF->getTarget().getMCAsmInfo()->getPrivateGlobalPrefix(); + return Ctx.GetOrCreateTemporarySymbol(Twine(Prefix) + "BB" + + Twine(MF->getFunctionNumber()) + "_" + + Twine(getNumber())); } diff --git a/lib/CodeGen/MachineCSE.cpp b/lib/CodeGen/MachineCSE.cpp index b376e3d..ce95d8d 100644 --- a/lib/CodeGen/MachineCSE.cpp +++ b/lib/CodeGen/MachineCSE.cpp @@ -33,9 +33,9 @@ namespace { class MachineCSE : public MachineFunctionPass { const TargetInstrInfo *TII; const TargetRegisterInfo *TRI; - MachineRegisterInfo *MRI; - MachineDominatorTree *DT; AliasAnalysis *AA; + MachineDominatorTree *DT; + MachineRegisterInfo *MRI; public: static char ID; // Pass identification MachineCSE() : MachineFunctionPass(&ID), CurrVN(0) {} @@ -61,6 +61,8 @@ namespace { MachineBasicBlock::const_iterator E); bool hasLivePhysRegDefUse(MachineInstr *MI, MachineBasicBlock *MBB); bool isCSECandidate(MachineInstr *MI); + bool isProfitableToCSE(unsigned CSReg, unsigned Reg, + MachineInstr *CSMI, MachineInstr *MI); bool ProcessBlock(MachineDomTreeNode *Node); }; } // end anonymous namespace @@ -92,7 +94,16 @@ bool MachineCSE::PerformTrivialCoalescing(MachineInstr *MI, if (TII->isMoveInstr(*DefMI, SrcReg, DstReg, SrcSubIdx, DstSubIdx) && TargetRegisterInfo::isVirtualRegister(SrcReg) && !SrcSubIdx && !DstSubIdx) { + const TargetRegisterClass *SRC = MRI->getRegClass(SrcReg); + const TargetRegisterClass *RC = MRI->getRegClass(Reg); + const TargetRegisterClass *NewRC = getCommonSubClass(RC, SRC); + if (!NewRC) + continue; + DEBUG(dbgs() << "Coalescing: " << *DefMI); + DEBUG(dbgs() << "*** to: " << *MI); MO.setReg(SrcReg); + if (NewRC != SRC) + MRI->setRegClass(SrcReg, NewRC); DefMI->eraseFromParent(); ++NumCoalesces; Changed = true; @@ -133,6 +144,8 @@ bool MachineCSE::isPhysDefTriviallyDead(unsigned Reg, return false; } +/// hasLivePhysRegDefUse - Return true if the specified instruction read / write +/// physical registers (except for dead defs of physical registers). bool MachineCSE::hasLivePhysRegDefUse(MachineInstr *MI, MachineBasicBlock *MBB){ unsigned PhysDef = 0; for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { @@ -167,12 +180,19 @@ bool MachineCSE::hasLivePhysRegDefUse(MachineInstr *MI, MachineBasicBlock *MBB){ return false; } -bool MachineCSE::isCSECandidate(MachineInstr *MI) { - // Ignore copies or instructions that read / write physical registers - // (except for dead defs of physical registers). +static bool isCopy(const MachineInstr *MI, const TargetInstrInfo *TII) { unsigned SrcReg, DstReg, SrcSubIdx, DstSubIdx; - if (TII->isMoveInstr(*MI, SrcReg, DstReg, SrcSubIdx, DstSubIdx) || - MI->isExtractSubreg() || MI->isInsertSubreg() || MI->isSubregToReg()) + return TII->isMoveInstr(*MI, SrcReg, DstReg, SrcSubIdx, DstSubIdx) || + MI->isExtractSubreg() || MI->isInsertSubreg() || MI->isSubregToReg(); +} + +bool MachineCSE::isCSECandidate(MachineInstr *MI) { + if (MI->isLabel() || MI->isPHI() || MI->isImplicitDef() || + MI->isKill() || MI->isInlineAsm()) + return false; + + // Ignore copies. + if (isCopy(MI, TII)) return false; // Ignore stuff that we obviously can't move. @@ -194,9 +214,69 @@ bool MachineCSE::isCSECandidate(MachineInstr *MI) { return true; } +/// isProfitableToCSE - Return true if it's profitable to eliminate MI with a +/// common expression that defines Reg. +bool MachineCSE::isProfitableToCSE(unsigned CSReg, unsigned Reg, + MachineInstr *CSMI, MachineInstr *MI) { + // FIXME: Heuristics that works around the lack the live range splitting. + + // Heuristics #1: Don't cse "cheap" computating if the def is not local or in an + // immediate predecessor. We don't want to increase register pressure and end up + // causing other computation to be spilled. + if (MI->getDesc().isAsCheapAsAMove()) { + MachineBasicBlock *CSBB = CSMI->getParent(); + MachineBasicBlock *BB = MI->getParent(); + if (CSBB != BB && + find(CSBB->succ_begin(), CSBB->succ_end(), BB) == CSBB->succ_end()) + return false; + } + + // Heuristics #2: If the expression doesn't not use a vr and the only use + // of the redundant computation are copies, do not cse. + bool HasVRegUse = false; + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + const MachineOperand &MO = MI->getOperand(i); + if (MO.isReg() && MO.isUse() && MO.getReg() && + TargetRegisterInfo::isVirtualRegister(MO.getReg())) { + HasVRegUse = true; + break; + } + } + if (!HasVRegUse) { + bool HasNonCopyUse = false; + for (MachineRegisterInfo::use_nodbg_iterator I = MRI->use_nodbg_begin(Reg), + E = MRI->use_nodbg_end(); I != E; ++I) { + MachineInstr *Use = &*I; + // Ignore copies. + if (!isCopy(Use, TII)) { + HasNonCopyUse = true; + break; + } + } + if (!HasNonCopyUse) + return false; + } + + // Heuristics #3: If the common subexpression is used by PHIs, do not reuse + // it unless the defined value is already used in the BB of the new use. + bool HasPHI = false; + SmallPtrSet<MachineBasicBlock*, 4> CSBBs; + for (MachineRegisterInfo::use_nodbg_iterator I = MRI->use_nodbg_begin(CSReg), + E = MRI->use_nodbg_end(); I != E; ++I) { + MachineInstr *Use = &*I; + HasPHI |= Use->isPHI(); + CSBBs.insert(Use->getParent()); + } + + if (!HasPHI) + return true; + return CSBBs.count(MI->getParent()); +} + bool MachineCSE::ProcessBlock(MachineDomTreeNode *Node) { bool Changed = false; + SmallVector<std::pair<unsigned, unsigned>, 8> CSEPairs; ScopedHashTableScope<MachineInstr*, unsigned, MachineInstrExpressionTrait> VNTS(VNT); MachineBasicBlock *MBB = Node->getBlock(); @@ -231,6 +311,9 @@ bool MachineCSE::ProcessBlock(MachineDomTreeNode *Node) { MachineInstr *CSMI = Exps[CSVN]; DEBUG(dbgs() << "Examining: " << *MI); DEBUG(dbgs() << "*** Found a common subexpression: " << *CSMI); + + // Check if it's profitable to perform this CSE. + bool DoCSE = true; unsigned NumDefs = MI->getDesc().getNumDefs(); for (unsigned i = 0, e = MI->getNumOperands(); NumDefs && i != e; ++i) { MachineOperand &MO = MI->getOperand(i); @@ -243,11 +326,26 @@ bool MachineCSE::ProcessBlock(MachineDomTreeNode *Node) { assert(TargetRegisterInfo::isVirtualRegister(OldReg) && TargetRegisterInfo::isVirtualRegister(NewReg) && "Do not CSE physical register defs!"); - MRI->replaceRegWith(OldReg, NewReg); + if (!isProfitableToCSE(NewReg, OldReg, CSMI, MI)) { + DoCSE = false; + break; + } + CSEPairs.push_back(std::make_pair(OldReg, NewReg)); --NumDefs; } - MI->eraseFromParent(); - ++NumCSEs; + + // Actually perform the elimination. + if (DoCSE) { + for (unsigned i = 0, e = CSEPairs.size(); i != e; ++i) + MRI->replaceRegWith(CSEPairs[i].first, CSEPairs[i].second); + MI->eraseFromParent(); + ++NumCSEs; + } else { + DEBUG(dbgs() << "*** Not profitable, avoid CSE!\n"); + VNT.insert(MI, CurrVN++); + Exps.push_back(MI); + } + CSEPairs.clear(); } // Recursively call ProcessBlock with childred. @@ -262,7 +360,7 @@ bool MachineCSE::runOnMachineFunction(MachineFunction &MF) { TII = MF.getTarget().getInstrInfo(); TRI = MF.getTarget().getRegisterInfo(); MRI = &MF.getRegInfo(); - DT = &getAnalysis<MachineDominatorTree>(); AA = &getAnalysis<AliasAnalysis>(); + DT = &getAnalysis<MachineDominatorTree>(); return ProcessBlock(DT->getRootNode()); } diff --git a/lib/CodeGen/MachineFunction.cpp b/lib/CodeGen/MachineFunction.cpp index 4377d5b..1e3cb1e 100644 --- a/lib/CodeGen/MachineFunction.cpp +++ b/lib/CodeGen/MachineFunction.cpp @@ -464,7 +464,9 @@ MCSymbol *MachineFunction::getJTISymbol(unsigned JTI, MCContext &Ctx, SmallString<60> Name; raw_svector_ostream(Name) << Prefix << "JTI" << getFunctionNumber() << '_' << JTI; - return Ctx.GetOrCreateSymbol(Name.str()); + if (isLinkerPrivate) + return Ctx.GetOrCreateSymbol(Name.str()); + return Ctx.GetOrCreateTemporarySymbol(Name.str()); } diff --git a/lib/CodeGen/MachineInstr.cpp b/lib/CodeGen/MachineInstr.cpp index e23670d..4c7cb8f 100644 --- a/lib/CodeGen/MachineInstr.cpp +++ b/lib/CodeGen/MachineInstr.cpp @@ -1219,7 +1219,7 @@ void MachineInstr::print(raw_ostream &OS, const TargetMachine *TM) const { DIScope Scope = DLT.getScope(); OS << " dbg:"; // Omit the directory, since it's usually long and uninteresting. - if (!Scope.isNull()) + if (Scope.Verify()) OS << Scope.getFilename(); else OS << "<unknown>"; diff --git a/lib/CodeGen/MachineModuleInfo.cpp b/lib/CodeGen/MachineModuleInfo.cpp index 5052af7..72fb9fd 100644 --- a/lib/CodeGen/MachineModuleInfo.cpp +++ b/lib/CodeGen/MachineModuleInfo.cpp @@ -185,7 +185,8 @@ void MachineModuleInfo::addCleanup(MachineBasicBlock *LandingPad) { void MachineModuleInfo::TidyLandingPads() { for (unsigned i = 0; i != LandingPads.size(); ) { LandingPadInfo &LandingPad = LandingPads[i]; - LandingPad.LandingPadLabel = MappedLabel(LandingPad.LandingPadLabel); + if (isLabelDeleted(LandingPad.LandingPadLabel)) + LandingPad.LandingPadLabel = 0; // Special case: we *should* emit LPs with null LP MBB. This indicates // "nounwind" case. @@ -195,17 +196,14 @@ void MachineModuleInfo::TidyLandingPads() { } for (unsigned j=0; j != LandingPads[i].BeginLabels.size(); ) { - unsigned BeginLabel = MappedLabel(LandingPad.BeginLabels[j]); - unsigned EndLabel = MappedLabel(LandingPad.EndLabels[j]); - - if (!BeginLabel || !EndLabel) { + unsigned BeginLabel = LandingPad.BeginLabels[j]; + unsigned EndLabel = LandingPad.EndLabels[j]; + if (isLabelDeleted(BeginLabel) || isLabelDeleted(EndLabel)) { LandingPad.BeginLabels.erase(LandingPad.BeginLabels.begin() + j); LandingPad.EndLabels.erase(LandingPad.EndLabels.begin() + j); continue; } - LandingPad.BeginLabels[j] = BeginLabel; - LandingPad.EndLabels[j] = EndLabel; ++j; } diff --git a/lib/CodeGen/PrologEpilogInserter.cpp b/lib/CodeGen/PrologEpilogInserter.cpp index 138e711..2d54cd4 100644 --- a/lib/CodeGen/PrologEpilogInserter.cpp +++ b/lib/CodeGen/PrologEpilogInserter.cpp @@ -57,6 +57,7 @@ bool PEI::runOnMachineFunction(MachineFunction &Fn) { const TargetRegisterInfo *TRI = Fn.getTarget().getRegisterInfo(); RS = TRI->requiresRegisterScavenging(Fn) ? new RegScavenger() : NULL; FrameIndexVirtualScavenging = TRI->requiresFrameIndexScavenging(Fn); + FrameConstantRegMap.clear(); // Get MachineModuleInfo so that we can track the construction of the // frame. @@ -685,7 +686,7 @@ void PEI::replaceFrameIndices(MachineFunction &Fn) { // If this instruction has a FrameIndex operand, we need to // use that target machine register info object to eliminate // it. - int Value; + TargetRegisterInfo::FrameIndexValue Value; unsigned VReg = TRI.eliminateFrameIndex(MI, SPAdj, &Value, FrameIndexVirtualScavenging ? NULL : RS); @@ -764,12 +765,12 @@ void PEI::scavengeFrameVirtualRegs(MachineFunction &Fn) { unsigned CurrentVirtReg = 0; unsigned CurrentScratchReg = 0; bool havePrevValue = false; - int PrevValue = 0; + TargetRegisterInfo::FrameIndexValue PrevValue(0,0); + TargetRegisterInfo::FrameIndexValue Value(0,0); MachineInstr *PrevLastUseMI = NULL; unsigned PrevLastUseOp = 0; bool trackingCurrentValue = false; int SPAdj = 0; - int Value = 0; // The instruction stream may change in the loop, so check BB->end() // directly. @@ -826,8 +827,11 @@ void PEI::scavengeFrameVirtualRegs(MachineFunction &Fn) { if (trackingCurrentValue) { SPAdj = (*Entry).second.second; Value = (*Entry).second.first; - } else - SPAdj = Value = 0; + } else { + SPAdj = 0; + Value.first = 0; + Value.second = 0; + } // If the scratch register from the last allocation is still // available, see if the value matches. If it does, just re-use it. diff --git a/lib/CodeGen/PrologEpilogInserter.h b/lib/CodeGen/PrologEpilogInserter.h index 931f1eb..aa95773 100644 --- a/lib/CodeGen/PrologEpilogInserter.h +++ b/lib/CodeGen/PrologEpilogInserter.h @@ -102,7 +102,8 @@ namespace llvm { // When using the scavenger post-pass to resolve frame reference // materialization registers, maintain a map of the registers to // the constant value and SP adjustment associated with it. - typedef std::pair<int, int> FrameConstantEntry; + typedef std::pair<TargetRegisterInfo::FrameIndexValue, int> + FrameConstantEntry; DenseMap<unsigned, FrameConstantEntry> FrameConstantRegMap; #ifndef NDEBUG diff --git a/lib/CodeGen/SelectionDAG/SDDbgValue.h b/lib/CodeGen/SelectionDAG/SDDbgValue.h index 9e15fc9..d43a044 100644 --- a/lib/CodeGen/SelectionDAG/SDDbgValue.h +++ b/lib/CodeGen/SelectionDAG/SDDbgValue.h @@ -34,14 +34,16 @@ class SDDbgValue { MDNode *mdPtr; uint64_t Offset; DebugLoc DL; + unsigned Order; public: // Constructor for non-constants. - SDDbgValue(MDNode *mdP, SDNode *N, unsigned R, uint64_t off, DebugLoc dl) : - Node(N), ResNo(R), Const(0), mdPtr(mdP), Offset(off), DL(dl) {} + SDDbgValue(MDNode *mdP, SDNode *N, unsigned R, uint64_t off, DebugLoc dl, + unsigned O) : + Node(N), ResNo(R), Const(0), mdPtr(mdP), Offset(off), DL(dl), Order(O) {} // Constructor for constants. - SDDbgValue(MDNode *mdP, Value *C, uint64_t off, DebugLoc dl) : Node(0), - ResNo(0), Const(C), mdPtr(mdP), Offset(off), DL(dl) {} + SDDbgValue(MDNode *mdP, Value *C, uint64_t off, DebugLoc dl, unsigned O) : + Node(0), ResNo(0), Const(C), mdPtr(mdP), Offset(off), DL(dl), Order(O) {} // Returns the MDNode pointer. MDNode *getMDPtr() { return mdPtr; } @@ -60,6 +62,10 @@ public: // Returns the DebugLoc. DebugLoc getDebugLoc() { return DL; } + + // Returns the SDNodeOrder. This is the order of the preceding node in the + // input. + unsigned getOrder() { return Order; } }; } // end llvm namespace diff --git a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index 023e486..746d4e2 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -3208,7 +3208,7 @@ bool MeetsMaxMemopRequirement(std::vector<EVT> &MemOps, bool isSrcConst = isa<ConstantSDNode>(Src); EVT VT = TLI.getOptimalMemOpType(Size, Align, isSrcConst, isSrcStr, DAG); bool AllowUnalign = TLI.allowsUnalignedMemoryAccesses(VT); - if (VT != MVT::iAny) { + if (VT != MVT::Other) { const Type *Ty = VT.getTypeForEVT(*DAG.getContext()); unsigned NewAlign = (unsigned) TLI.getTargetData()->getABITypeAlignment(Ty); // If source is a string constant, this will require an unaligned load. @@ -3216,14 +3216,14 @@ bool MeetsMaxMemopRequirement(std::vector<EVT> &MemOps, if (Dst.getOpcode() != ISD::FrameIndex) { // Can't change destination alignment. It requires a unaligned store. if (AllowUnalign) - VT = MVT::iAny; + VT = MVT::Other; } else { int FI = cast<FrameIndexSDNode>(Dst)->getIndex(); MachineFrameInfo *MFI = DAG.getMachineFunction().getFrameInfo(); if (MFI->isFixedObjectIndex(FI)) { // Can't change destination alignment. It requires a unaligned store. if (AllowUnalign) - VT = MVT::iAny; + VT = MVT::Other; } else { // Give the stack frame object a larger alignment if needed. if (MFI->getObjectAlignment(FI) < NewAlign) @@ -3234,7 +3234,7 @@ bool MeetsMaxMemopRequirement(std::vector<EVT> &MemOps, } } - if (VT == MVT::iAny) { + if (VT == MVT::Other) { if (TLI.allowsUnalignedMemoryAccesses(MVT::i64)) { VT = MVT::i64; } else { diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp index 05f9f1f..a82f0f7 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp @@ -2141,6 +2141,9 @@ SelectCodeCommon(SDNode *NodeToMatch, const unsigned char *MatcherTable, while (1) { assert(MatcherIndex < TableSize && "Invalid index"); +#ifndef NDEBUG + unsigned CurrentOpcodeIndex = MatcherIndex; +#endif BuiltinOpcodes Opcode = (BuiltinOpcodes)MatcherTable[MatcherIndex++]; switch (Opcode) { case OPC_Scope: { @@ -2666,6 +2669,7 @@ SelectCodeCommon(SDNode *NodeToMatch, const unsigned char *MatcherTable, // If the code reached this point, then the match failed. See if there is // another child to try in the current 'Scope', otherwise pop it until we // find a case to check. + DEBUG(errs() << " Match failed at index " << CurrentOpcodeIndex << "\n"); while (1) { if (MatchScopes.empty()) { CannotYetSelect(NodeToMatch); @@ -2680,13 +2684,12 @@ SelectCodeCommon(SDNode *NodeToMatch, const unsigned char *MatcherTable, NodeStack.append(LastScope.NodeStack.begin(), LastScope.NodeStack.end()); N = NodeStack.back(); - DEBUG(errs() << " Match failed at index " << MatcherIndex - << " continuing at " << LastScope.FailIndex << "\n"); - if (LastScope.NumMatchedMemRefs != MatchedMemRefs.size()) MatchedMemRefs.resize(LastScope.NumMatchedMemRefs); MatcherIndex = LastScope.FailIndex; + DEBUG(errs() << " Continuing at " << MatcherIndex << "\n"); + InputChain = LastScope.InputChain; InputFlag = LastScope.InputFlag; if (!LastScope.HasChainNodesMatched) diff --git a/lib/CodeGen/SimpleRegisterCoalescing.cpp b/lib/CodeGen/SimpleRegisterCoalescing.cpp index ce72b2f..d25df1d 100644 --- a/lib/CodeGen/SimpleRegisterCoalescing.cpp +++ b/lib/CodeGen/SimpleRegisterCoalescing.cpp @@ -1671,8 +1671,20 @@ bool SimpleRegisterCoalescing::JoinCopy(CopyRec &TheCopy, bool &Again) { // density, do not join them, instead mark the physical register as its // allocation preference. LiveInterval &JoinVInt = SrcIsPhys ? DstInt : SrcInt; + LiveInterval &JoinPInt = SrcIsPhys ? SrcInt : DstInt; unsigned JoinVReg = SrcIsPhys ? DstReg : SrcReg; unsigned JoinPReg = SrcIsPhys ? SrcReg : DstReg; + + // Don't join with physregs that have a ridiculous number of live + // ranges. The data structure performance is really bad when that + // happens. + if (JoinPInt.ranges.size() > 1000) { + mri_->setRegAllocationHint(JoinVInt.reg, 0, JoinPReg); + ++numAborts; + DEBUG(dbgs() << "\tPhysical register too complicated, abort!\n"); + return false; + } + const TargetRegisterClass *RC = mri_->getRegClass(JoinVReg); unsigned Threshold = allocatableRCRegs_[RC].count() * 2; unsigned Length = li_->getApproximateInstructionCount(JoinVInt); diff --git a/lib/CodeGen/TargetLoweringObjectFileImpl.cpp b/lib/CodeGen/TargetLoweringObjectFileImpl.cpp index 3b3be5d..2014b42 100644 --- a/lib/CodeGen/TargetLoweringObjectFileImpl.cpp +++ b/lib/CodeGen/TargetLoweringObjectFileImpl.cpp @@ -403,12 +403,15 @@ getSymbolForDwarfGlobalReference(const GlobalValue *GV, Mangler *Mang, // Add information about the stub reference to ELFMMI so that the stub // gets emitted by the asmprinter. - MCSymbol *Sym = getContext().GetOrCreateSymbol(Name.str()); + MCSymbol *Sym = getContext().GetOrCreateTemporarySymbol(Name.str()); MCSymbol *&StubSym = ELFMMI.getGVStubEntry(Sym); if (StubSym == 0) { Name.clear(); Mang->getNameWithPrefix(Name, GV, false); - StubSym = getContext().GetOrCreateSymbol(Name.str()); + if (GV->hasPrivateLinkage()) + StubSym = getContext().GetOrCreateTemporarySymbol(Name.str()); + else + StubSym = getContext().GetOrCreateSymbol(Name.str()); } return TargetLoweringObjectFile:: @@ -463,6 +466,14 @@ getMachOSection(StringRef Segment, StringRef Section, void TargetLoweringObjectFileMachO::Initialize(MCContext &Ctx, const TargetMachine &TM) { + // _foo.eh symbols are currently always exported so that the linker knows + // about them. This is not necessary on 10.6 and later, but it + // doesn't hurt anything. + // FIXME: I need to get this from Triple. + IsFunctionEHSymbolGlobal = true; + IsFunctionEHFrameSymbolPrivate = false; + SupportsWeakOmittedEHFrame = false; + if (UniquingMap != 0) ((MachOUniqueMapTy*)UniquingMap)->clear(); TargetLoweringObjectFile::Initialize(Ctx, TM); @@ -651,16 +662,16 @@ SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind, } // FIXME: Alignment check should be handled by section classifier. - if (Kind.isMergeable1ByteCString() || - (Kind.isMergeable2ByteCString() && !GV->hasExternalLinkage())) { - if (TM.getTargetData()->getPreferredAlignment( - cast<GlobalVariable>(GV)) < 32) { - if (Kind.isMergeable1ByteCString()) - return CStringSection; - assert(Kind.isMergeable2ByteCString()); - return UStringSection; - } - } + if (Kind.isMergeable1ByteCString() && + TM.getTargetData()->getPreferredAlignment(cast<GlobalVariable>(GV)) < 32) + return CStringSection; + + // Do not put 16-bit arrays in the UString section if they have an + // externally visible label, this runs into issues with certain linker + // versions. + if (Kind.isMergeable2ByteCString() && !GV->hasExternalLinkage() && + TM.getTargetData()->getPreferredAlignment(cast<GlobalVariable>(GV)) < 32) + return UStringSection; if (Kind.isMergeableConst()) { if (Kind.isMergeableConst4()) @@ -749,12 +760,15 @@ getSymbolForDwarfGlobalReference(const GlobalValue *GV, Mangler *Mang, // Add information about the stub reference to MachOMMI so that the stub // gets emitted by the asmprinter. - MCSymbol *Sym = getContext().GetOrCreateSymbol(Name.str()); + MCSymbol *Sym = getContext().GetOrCreateTemporarySymbol(Name.str()); MCSymbol *&StubSym = MachOMMI.getGVStubEntry(Sym); if (StubSym == 0) { Name.clear(); Mang->getNameWithPrefix(Name, GV, false); - StubSym = getContext().GetOrCreateSymbol(Name.str()); + if (GV->hasPrivateLinkage()) + StubSym = getContext().GetOrCreateTemporarySymbol(Name.str()); + else + StubSym = getContext().GetOrCreateSymbol(Name.str()); } return TargetLoweringObjectFile:: diff --git a/lib/ExecutionEngine/JIT/JITDwarfEmitter.cpp b/lib/ExecutionEngine/JIT/JITDwarfEmitter.cpp index 946351b..da5435a 100644 --- a/lib/ExecutionEngine/JIT/JITDwarfEmitter.cpp +++ b/lib/ExecutionEngine/JIT/JITDwarfEmitter.cpp @@ -75,10 +75,9 @@ JITDwarfEmitter::EmitFrameMoves(intptr_t BaseLabelPtr, unsigned LabelID = Move.getLabelID(); if (LabelID) { - LabelID = MMI->MappedLabel(LabelID); - // Throw out move if the label is invalid. - if (!LabelID) continue; + if (MMI->isLabelDeleted(LabelID)) + continue; } intptr_t LabelPtr = 0; @@ -722,10 +721,9 @@ JITDwarfEmitter::GetFrameMovesSizeInBytes(intptr_t BaseLabelPtr, unsigned LabelID = Move.getLabelID(); if (LabelID) { - LabelID = MMI->MappedLabel(LabelID); - // Throw out move if the label is invalid. - if (!LabelID) continue; + if (MMI->isLabelDeleted(LabelID)) + continue; } intptr_t LabelPtr = 0; diff --git a/lib/MC/MCAsmInfo.cpp b/lib/MC/MCAsmInfo.cpp index f3f063f..bda700b 100644 --- a/lib/MC/MCAsmInfo.cpp +++ b/lib/MC/MCAsmInfo.cpp @@ -68,9 +68,6 @@ MCAsmInfo::MCAsmInfo() { ExceptionsType = ExceptionHandling::None; DwarfRequiresFrameSection = true; DwarfUsesInlineInfoSection = false; - Is_EHSymbolPrivate = true; - GlobalEHDirective = 0; - SupportsWeakOmittedEHFrame = true; DwarfSectionOffsetDirective = 0; AsmTransCBE = 0; diff --git a/lib/MC/MCAsmInfoDarwin.cpp b/lib/MC/MCAsmInfoDarwin.cpp index da865ad..3c31caa 100644 --- a/lib/MC/MCAsmInfoDarwin.cpp +++ b/lib/MC/MCAsmInfoDarwin.cpp @@ -40,19 +40,8 @@ MCAsmInfoDarwin::MCAsmInfoDarwin() { HiddenVisibilityAttr = MCSA_PrivateExtern; // Doesn't support protected visibility. ProtectedVisibilityAttr = MCSA_Global; - HasDotTypeDotSizeDirective = false; HasNoDeadStrip = true; - // Note: Even though darwin has the .lcomm directive, it is just a synonym for - // zerofill, so we prefer to use .zerofill. - - // _foo.eh symbols are currently always exported so that the linker knows - // about them. This is not necessary on 10.6 and later, but it - // doesn't hurt anything. - // FIXME: I need to get this from Triple. - Is_EHSymbolPrivate = false; - GlobalEHDirective = "\t.globl\t"; - SupportsWeakOmittedEHFrame = false; } diff --git a/lib/MC/MCAssembler.cpp b/lib/MC/MCAssembler.cpp index 96227db..00b02e0 100644 --- a/lib/MC/MCAssembler.cpp +++ b/lib/MC/MCAssembler.cpp @@ -440,29 +440,49 @@ public: DenseMap<const MCSymbol*,MCSymbolData*> &SymbolMap, std::vector<MachRelocationEntry> &Relocs) { uint32_t Address = Fragment.getOffset() + Fixup.Offset; - unsigned IsPCRel = 0; + unsigned IsPCRel = isFixupKindPCRel(Fixup.Kind); unsigned Log2Size = getFixupKindLog2Size(Fixup.Kind); unsigned Type = RIT_Vanilla; // See <reloc.h>. const MCSymbol *A = Target.getSymA(); - MCSymbolData *SD = SymbolMap.lookup(A); - uint32_t Value = SD->getFragment()->getAddress() + SD->getOffset(); + MCSymbolData *A_SD = SymbolMap.lookup(A); + + if (!A_SD->getFragment()) + llvm_report_error("symbol '" + A->getName() + + "' can not be undefined in a subtraction expression"); + + uint32_t Value = A_SD->getFragment()->getAddress() + A_SD->getOffset(); uint32_t Value2 = 0; if (const MCSymbol *B = Target.getSymB()) { - Type = RIT_LocalDifference; + MCSymbolData *B_SD = SymbolMap.lookup(B); + + if (!B_SD->getFragment()) + llvm_report_error("symbol '" + B->getName() + + "' can not be undefined in a subtraction expression"); - MCSymbolData *SD = SymbolMap.lookup(B); - Value2 = SD->getFragment()->getAddress() + SD->getOffset(); + // Select the appropriate difference relocation type. + // + // Note that there is no longer any semantic difference between these two + // relocation types from the linkers point of view, this is done solely + // for pedantic compatibility with 'as'. + Type = A_SD->isExternal() ? RIT_Difference : RIT_LocalDifference; + Value2 = B_SD->getFragment()->getAddress() + B_SD->getOffset(); } // The value which goes in the fixup is current value of the expression. Fixup.FixedValue = Value - Value2 + Target.getConstant(); - if (isFixupKindPCRel(Fixup.Kind)) { + if (IsPCRel) Fixup.FixedValue -= Address; - IsPCRel = 1; - } + + // If this fixup is a vanilla PC relative relocation for a local label, we + // don't need a relocation. + // + // FIXME: Implement proper atom support. + if (IsPCRel && Target.getSymA() && Target.getSymA()->isTemporary() && + !Target.getSymB()) + return; MachRelocationEntry MRE; MRE.Word0 = ((Address << 0) | @@ -473,14 +493,12 @@ public: MRE.Word1 = Value; Relocs.push_back(MRE); - if (Type == RIT_LocalDifference) { - Type = RIT_Pair; - + if (Type == RIT_Difference || Type == RIT_LocalDifference) { MachRelocationEntry MRE; MRE.Word0 = ((0 << 0) | - (Type << 24) | + (RIT_Pair << 24) | (Log2Size << 28) | - (0 << 30) | + (IsPCRel << 30) | RF_Scattered); MRE.Word1 = Value2; Relocs.push_back(MRE); @@ -491,15 +509,21 @@ public: MCAsmFixup &Fixup, DenseMap<const MCSymbol*,MCSymbolData*> &SymbolMap, std::vector<MachRelocationEntry> &Relocs) { + unsigned IsPCRel = isFixupKindPCRel(Fixup.Kind); + unsigned Log2Size = getFixupKindLog2Size(Fixup.Kind); + MCValue Target; if (!Fixup.Value->EvaluateAsRelocatable(Target)) llvm_report_error("expected relocatable expression"); - // If this is a difference or a local symbol plus an offset, then we need a - // scattered relocation entry. + // If this is a difference or a defined symbol plus an offset, then we need + // a scattered relocation entry. + uint32_t Offset = Target.getConstant(); + if (IsPCRel) + Offset += 1 << Log2Size; if (Target.getSymB() || (Target.getSymA() && !Target.getSymA()->isUndefined() && - Target.getConstant())) + Offset)) return ComputeScatteredRelocationInfo(Asm, Fragment, Fixup, Target, SymbolMap, Relocs); @@ -507,8 +531,6 @@ public: uint32_t Address = Fragment.getOffset() + Fixup.Offset; uint32_t Value = 0; unsigned Index = 0; - unsigned IsPCRel = 0; - unsigned Log2Size = getFixupKindLog2Size(Fixup.Kind); unsigned IsExtern = 0; unsigned Type = 0; @@ -545,11 +567,15 @@ public: // The value which goes in the fixup is current value of the expression. Fixup.FixedValue = Value + Target.getConstant(); - - if (isFixupKindPCRel(Fixup.Kind)) { + if (IsPCRel) Fixup.FixedValue -= Address; - IsPCRel = 1; - } + + // If this fixup is a vanilla PC relative relocation for a local label, we + // don't need a relocation. + // + // FIXME: Implement proper atom support. + if (IsPCRel && Target.getSymA() && Target.getSymA()->isTemporary()) + return; // struct relocation_info (8 bytes) MachRelocationEntry MRE; @@ -1040,8 +1066,8 @@ void MCAssembler::LayoutSection(MCSectionData &SD) { // Align the fragment offset; it is safe to adjust the offset freely since // this is only in virtual sections. - uint64_t Aligned = RoundUpToAlignment(Address, ZFF.getAlignment()); - F.setOffset(Aligned - SD.getAddress()); + Address = RoundUpToAlignment(Address, ZFF.getAlignment()); + F.setOffset(Address - SD.getAddress()); // FIXME: This is misnamed. F.setFileSize(ZFF.getSize()); @@ -1270,9 +1296,15 @@ void MCAssembler::Finish() { if (!isVirtualSection(SD.getSection())) continue; + // Align this section if necessary by adding padding bytes to the previous + // section. + if (uint64_t Pad = OffsetToAlignment(Address, it->getAlignment())) + Address += Pad; + SD.setAddress(Address); LayoutSection(SD); Address += SD.getSize(); + } DEBUG_WITH_TYPE("mc-dump", { @@ -1336,7 +1368,7 @@ void MCDataFragment::dump() { OS << ",\n "; OS << " Fixups:["; for (fixup_iterator it = fixup_begin(), ie = fixup_end(); it != ie; ++it) { - if (it != fixup_begin()) OS << ",\n "; + if (it != fixup_begin()) OS << ",\n "; OS << *it; } OS << "]"; @@ -1379,7 +1411,7 @@ void MCSectionData::dump() { OS << "<MCSectionData"; OS << " Alignment:" << getAlignment() << " Address:" << Address << " Size:" << Size << " FileSize:" << FileSize - << " Fragments:["; + << " Fragments:[\n "; for (iterator it = begin(), ie = end(); it != ie; ++it) { if (it != begin()) OS << ",\n "; it->dump(); @@ -1407,7 +1439,7 @@ void MCAssembler::dump() { raw_ostream &OS = llvm::errs(); OS << "<MCAssembler\n"; - OS << " Sections:["; + OS << " Sections:[\n "; for (iterator it = begin(), ie = end(); it != ie; ++it) { if (it != begin()) OS << ",\n "; it->dump(); @@ -1416,7 +1448,7 @@ void MCAssembler::dump() { OS << " Symbols:["; for (symbol_iterator it = symbol_begin(), ie = symbol_end(); it != ie; ++it) { - if (it != symbol_begin()) OS << ",\n "; + if (it != symbol_begin()) OS << ",\n "; it->dump(); } OS << "]>\n"; diff --git a/lib/MC/MCContext.cpp b/lib/MC/MCContext.cpp index 45d2c02..63264f6 100644 --- a/lib/MC/MCContext.cpp +++ b/lib/MC/MCContext.cpp @@ -23,16 +23,8 @@ MCContext::~MCContext() { // we don't need to free them here. } -MCSymbol *MCContext::CreateSymbol(StringRef Name) { - assert(Name[0] != '\0' && "Normal symbols cannot be unnamed!"); - - // Create and bind the symbol, and ensure that names are unique. - MCSymbol *&Entry = Symbols[Name]; - assert(!Entry && "Duplicate symbol definition!"); - return Entry = new (*this) MCSymbol(Name, false); -} - MCSymbol *MCContext::GetOrCreateSymbol(StringRef Name) { + assert(!Name.empty() && "Normal symbols cannot be unnamed!"); MCSymbol *&Entry = Symbols[Name]; if (Entry) return Entry; @@ -46,17 +38,24 @@ MCSymbol *MCContext::GetOrCreateSymbol(const Twine &Name) { } -MCSymbol *MCContext::CreateTemporarySymbol(StringRef Name) { +MCSymbol *MCContext::GetOrCreateTemporarySymbol(StringRef Name) { // If unnamed, just create a symbol. if (Name.empty()) new (*this) MCSymbol("", true); // Otherwise create as usual. MCSymbol *&Entry = Symbols[Name]; - assert(!Entry && "Duplicate symbol definition!"); + if (Entry) return Entry; return Entry = new (*this) MCSymbol(Name, true); } +MCSymbol *MCContext::GetOrCreateTemporarySymbol(const Twine &Name) { + SmallString<128> NameSV; + Name.toVector(NameSV); + return GetOrCreateTemporarySymbol(NameSV.str()); +} + + MCSymbol *MCContext::LookupSymbol(StringRef Name) const { return Symbols.lookup(Name); } diff --git a/lib/MC/MCExpr.cpp b/lib/MC/MCExpr.cpp index e419043..4439eba 100644 --- a/lib/MC/MCExpr.cpp +++ b/lib/MC/MCExpr.cpp @@ -133,6 +133,11 @@ const MCSymbolRefExpr *MCSymbolRefExpr::Create(StringRef Name, MCContext &Ctx) { return Create(Ctx.GetOrCreateSymbol(Name), Ctx); } +const MCSymbolRefExpr *MCSymbolRefExpr::CreateTemp(StringRef Name, + MCContext &Ctx) { + return Create(Ctx.GetOrCreateTemporarySymbol(Name), Ctx); +} + void MCTargetExpr::Anchor() {} /* *** */ diff --git a/lib/MC/MCNullStreamer.cpp b/lib/MC/MCNullStreamer.cpp index ab61799..5f0c64a 100644 --- a/lib/MC/MCNullStreamer.cpp +++ b/lib/MC/MCNullStreamer.cpp @@ -29,7 +29,11 @@ namespace { CurSection = Section; } - virtual void EmitLabel(MCSymbol *Symbol) {} + virtual void EmitLabel(MCSymbol *Symbol) { + assert(Symbol->isUndefined() && "Cannot define a symbol twice!"); + assert(CurSection && "Cannot emit before setting section!"); + Symbol->setSection(*CurSection); + } virtual void EmitAssemblerFlag(MCAssemblerFlag Flag) {} diff --git a/lib/MC/MCParser/AsmParser.cpp b/lib/MC/MCParser/AsmParser.cpp index 6185c30..fc8d549 100644 --- a/lib/MC/MCParser/AsmParser.cpp +++ b/lib/MC/MCParser/AsmParser.cpp @@ -240,14 +240,10 @@ bool AsmParser::ParseParenExpr(const MCExpr *&Res, SMLoc &EndLoc) { } MCSymbol *AsmParser::CreateSymbol(StringRef Name) { - if (MCSymbol *S = Ctx.LookupSymbol(Name)) - return S; - // If the label starts with L it is an assembler temporary label. if (Name.startswith("L")) - return Ctx.CreateTemporarySymbol(Name); - - return Ctx.CreateSymbol(Name); + return Ctx.GetOrCreateTemporarySymbol(Name); + return Ctx.GetOrCreateSymbol(Name); } /// ParsePrimaryExpr - Parse a primary expression and return it. diff --git a/lib/MC/MCStreamer.cpp b/lib/MC/MCStreamer.cpp index 15b3079..703acc4 100644 --- a/lib/MC/MCStreamer.cpp +++ b/lib/MC/MCStreamer.cpp @@ -31,6 +31,11 @@ void MCStreamer::EmitIntValue(uint64_t Value, unsigned Size, EmitValue(MCConstantExpr::Create(Value, getContext()), Size, AddrSpace); } +void MCStreamer::EmitSymbolValue(const MCSymbol *Sym, unsigned Size, + unsigned AddrSpace) { + EmitValue(MCSymbolRefExpr::Create(Sym, getContext()), Size, AddrSpace); +} + /// EmitFill - Emit NumBytes bytes worth of the value specified by /// FillValue. This implements directives such as '.space'. void MCStreamer::EmitFill(uint64_t NumBytes, uint8_t FillValue, diff --git a/lib/Support/APFloat.cpp b/lib/Support/APFloat.cpp index 619f061..8f860a6 100644 --- a/lib/Support/APFloat.cpp +++ b/lib/Support/APFloat.cpp @@ -3366,7 +3366,7 @@ namespace { void APFloat::toString(SmallVectorImpl<char> &Str, unsigned FormatPrecision, - unsigned FormatMaxPadding) { + unsigned FormatMaxPadding) const { switch (category) { case fcInfinity: if (isNegative()) diff --git a/lib/Target/ARM/ARMBaseInstrInfo.h b/lib/Target/ARM/ARMBaseInstrInfo.h index e095acc..0194231 100644 --- a/lib/Target/ARM/ARMBaseInstrInfo.h +++ b/lib/Target/ARM/ARMBaseInstrInfo.h @@ -332,7 +332,7 @@ bool isJumpTableBranchOpcode(int Opc) { static inline bool isIndirectBranchOpcode(int Opc) { - return Opc == ARM::BRIND || Opc == ARM::tBRIND; + return Opc == ARM::BRIND || Opc == ARM::MOVPCRX || Opc == ARM::tBRIND; } /// getInstrPredicate - If instruction is predicated, returns its predicate diff --git a/lib/Target/ARM/ARMBaseRegisterInfo.cpp b/lib/Target/ARM/ARMBaseRegisterInfo.cpp index 577c363..d9b8323 100644 --- a/lib/Target/ARM/ARMBaseRegisterInfo.cpp +++ b/lib/Target/ARM/ARMBaseRegisterInfo.cpp @@ -40,7 +40,7 @@ #include "llvm/Support/CommandLine.h" using namespace llvm; -static cl::opt<bool> +cl::opt<bool> ReuseFrameIndexVals("arm-reuse-frame-index-vals", cl::Hidden, cl::init(true), cl::desc("Reuse repeated frame index values")); @@ -1153,7 +1153,7 @@ eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, unsigned ARMBaseRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, - int SPAdj, int *Value, + int SPAdj, FrameIndexValue *Value, RegScavenger *RS) const { unsigned i = 0; MachineInstr &MI = *II; @@ -1205,7 +1205,10 @@ ARMBaseRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, MI.getOperand(i).ChangeToRegister(FrameReg, false, false, false); else { ScratchReg = MF.getRegInfo().createVirtualRegister(ARM::GPRRegisterClass); - if (Value) *Value = Offset; + if (Value) { + Value->first = FrameReg; // use the frame register as a kind indicator + Value->second = Offset; + } if (!AFI->isThumbFunction()) emitARMRegPlusImmediate(MBB, II, MI.getDebugLoc(), ScratchReg, FrameReg, Offset, Pred, PredReg, TII); diff --git a/lib/Target/ARM/ARMBaseRegisterInfo.h b/lib/Target/ARM/ARMBaseRegisterInfo.h index 64f6ff1..456c392 100644 --- a/lib/Target/ARM/ARMBaseRegisterInfo.h +++ b/lib/Target/ARM/ARMBaseRegisterInfo.h @@ -145,7 +145,7 @@ public: MachineBasicBlock::iterator I) const; virtual unsigned eliminateFrameIndex(MachineBasicBlock::iterator II, - int SPAdj, int *Value = NULL, + int SPAdj, FrameIndexValue *Value = NULL, RegScavenger *RS = NULL) const; virtual void emitPrologue(MachineFunction &MF) const; diff --git a/lib/Target/ARM/ARMCodeEmitter.cpp b/lib/Target/ARM/ARMCodeEmitter.cpp index bd703f4..108a244 100644 --- a/lib/Target/ARM/ARMCodeEmitter.cpp +++ b/lib/Target/ARM/ARMCodeEmitter.cpp @@ -1138,7 +1138,7 @@ void ARMCodeEmitter::emitMiscBranchInstruction(const MachineInstr &MI) { // Set the conditional execution predicate Binary |= II->getPredicate(&MI) << ARMII::CondShift; - if (TID.Opcode == ARM::BX_RET) + if (TID.Opcode == ARM::BX_RET || TID.Opcode == ARM::MOVPCLR) // The return register is LR. Binary |= ARMRegisterInfo::getRegisterNumbering(ARM::LR); else diff --git a/lib/Target/ARM/ARMISelLowering.cpp b/lib/Target/ARM/ARMISelLowering.cpp index 6a2c6bb..3dd0313 100644 --- a/lib/Target/ARM/ARMISelLowering.cpp +++ b/lib/Target/ARM/ARMISelLowering.cpp @@ -37,9 +37,9 @@ #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/PseudoSourceValue.h" #include "llvm/CodeGen/SelectionDAG.h" +#include "llvm/MC/MCSectionMachO.h" #include "llvm/Target/TargetOptions.h" #include "llvm/ADT/VectorExtras.h" -#include "llvm/Support/CommandLine.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/raw_ostream.h" @@ -130,7 +130,8 @@ void ARMTargetLowering::addQRTypeForNEON(EVT VT) { static TargetLoweringObjectFile *createTLOF(TargetMachine &TM) { if (TM.getSubtarget<ARMSubtarget>().isTargetDarwin()) - return new TargetLoweringObjectFileMachO(); + return new ARMMachOTargetObjectFile(); + return new ARMElfTargetObjectFile(); } diff --git a/lib/Target/ARM/ARMInstrInfo.td b/lib/Target/ARM/ARMInstrInfo.td index 87c6f6e..af82a5f 100644 --- a/lib/Target/ARM/ARMInstrInfo.td +++ b/lib/Target/ARM/ARMInstrInfo.td @@ -21,7 +21,7 @@ def SDT_ARMCallSeqEnd : SDCallSeqEnd<[ SDTCisVT<0, i32>, SDTCisVT<1, i32> ]>; def SDT_ARMSaveCallPC : SDTypeProfile<0, 1, []>; -def SDT_ARMcall : SDTypeProfile<0, -1, [SDTCisInt<0>]>; +def SDT_ARMcall : SDTypeProfile<0, -1, [SDTCisPtrTy<0>]>; def SDT_ARMCMov : SDTypeProfile<1, 3, [SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>, @@ -113,6 +113,8 @@ def ARMrbit : SDNode<"ARMISD::RBIT", SDTIntUnaryOp>; //===----------------------------------------------------------------------===// // ARM Instruction Predicate Definitions. // +def HasV4T : Predicate<"Subtarget->hasV4TOps()">; +def NoV4T : Predicate<"!Subtarget->hasV4TOps()">; def HasV5T : Predicate<"Subtarget->hasV5TOps()">; def HasV5TE : Predicate<"Subtarget->hasV5TEOps()">; def HasV6 : Predicate<"Subtarget->hasV6Ops()">; @@ -851,24 +853,50 @@ def LEApcrelJT : AXI1<0x0, (outs GPR:$dst), // Control Flow Instructions. // -let isReturn = 1, isTerminator = 1, isBarrier = 1 in +let isReturn = 1, isTerminator = 1, isBarrier = 1 in { + // ARMV4T and above def BX_RET : AI<(outs), (ins), BrMiscFrm, IIC_Br, - "bx", "\tlr", [(ARMretflag)]> { - let Inst{3-0} = 0b1110; - let Inst{7-4} = 0b0001; - let Inst{19-8} = 0b111111111111; - let Inst{27-20} = 0b00010010; + "bx", "\tlr", [(ARMretflag)]>, + Requires<[IsARM, HasV4T]> { + let Inst{3-0} = 0b1110; + let Inst{7-4} = 0b0001; + let Inst{19-8} = 0b111111111111; + let Inst{27-20} = 0b00010010; + } + + // ARMV4 only + def MOVPCLR : AI<(outs), (ins), BrMiscFrm, IIC_Br, + "mov", "\tpc, lr", [(ARMretflag)]>, + Requires<[IsARM, NoV4T]> { + let Inst{11-0} = 0b000000001110; + let Inst{15-12} = 0b1111; + let Inst{19-16} = 0b0000; + let Inst{27-20} = 0b00011010; + } } // Indirect branches let isBranch = 1, isTerminator = 1, isBarrier = 1, isIndirectBranch = 1 in { + // ARMV4T and above def BRIND : AXI<(outs), (ins GPR:$dst), BrMiscFrm, IIC_Br, "bx\t$dst", - [(brind GPR:$dst)]> { + [(brind GPR:$dst)]>, + Requires<[IsARM, HasV4T]> { let Inst{7-4} = 0b0001; let Inst{19-8} = 0b111111111111; let Inst{27-20} = 0b00010010; let Inst{31-28} = 0b1110; } + + // ARMV4 only + def MOVPCRX : AXI<(outs), (ins GPR:$dst), BrMiscFrm, IIC_Br, "mov\tpc, $dst", + [(brind GPR:$dst)]>, + Requires<[IsARM, NoV4T]> { + let Inst{11-4} = 0b00000000; + let Inst{15-12} = 0b1111; + let Inst{19-16} = 0b0000; + let Inst{27-20} = 0b00011010; + let Inst{31-28} = 0b1110; + } } // FIXME: remove when we have a way to marking a MI with these properties. @@ -913,11 +941,22 @@ let isCall = 1, def BX : ABXIx2<(outs), (ins tGPR:$func, variable_ops), IIC_Br, "mov\tlr, pc\n\tbx\t$func", [(ARMcall_nolink tGPR:$func)]>, - Requires<[IsARM, IsNotDarwin]> { + Requires<[IsARM, HasV4T, IsNotDarwin]> { let Inst{7-4} = 0b0001; let Inst{19-8} = 0b111111111111; let Inst{27-20} = 0b00010010; } + + // ARMv4 + def BMOVPCRX : ABXIx2<(outs), (ins tGPR:$func, variable_ops), + IIC_Br, "mov\tlr, pc\n\tmov\tpc, $func", + [(ARMcall_nolink tGPR:$func)]>, + Requires<[IsARM, NoV4T, IsNotDarwin]> { + let Inst{11-4} = 0b00000000; + let Inst{15-12} = 0b1111; + let Inst{19-16} = 0b0000; + let Inst{27-20} = 0b00011010; + } } // On Darwin R9 is call-clobbered. @@ -950,11 +989,23 @@ let isCall = 1, // Note: Restrict $func to the tGPR regclass to prevent it being in LR. def BXr9 : ABXIx2<(outs), (ins tGPR:$func, variable_ops), IIC_Br, "mov\tlr, pc\n\tbx\t$func", - [(ARMcall_nolink tGPR:$func)]>, Requires<[IsARM, IsDarwin]> { + [(ARMcall_nolink tGPR:$func)]>, + Requires<[IsARM, HasV4T, IsDarwin]> { let Inst{7-4} = 0b0001; let Inst{19-8} = 0b111111111111; let Inst{27-20} = 0b00010010; } + + // ARMv4 + def BMOVPCRXr9 : ABXIx2<(outs), (ins tGPR:$func, variable_ops), + IIC_Br, "mov\tlr, pc\n\tmov\tpc, $func", + [(ARMcall_nolink tGPR:$func)]>, + Requires<[IsARM, NoV4T, IsDarwin]> { + let Inst{11-4} = 0b00000000; + let Inst{15-12} = 0b1111; + let Inst{19-16} = 0b0000; + let Inst{27-20} = 0b00011010; + } } let isBranch = 1, isTerminator = 1 in { @@ -2793,29 +2844,29 @@ def MRSsys : ABI<0b0001,(outs GPR:$dst),(ins), NoItinerary,"mrs","\t$dst, spsr", let Inst{7-4} = 0b0000; } -// FIXME: mask is ignored for the time being. -def MSR : ABI<0b0001,(outs),(ins GPR:$src), NoItinerary, "msr", "\tcpsr, $src", +def MSR : ABI<0b0001, (outs), (ins GPR:$src, i32imm:$mask), NoItinerary, "msr", + "\tcpsr${mask:msr}, $src", [/* For disassembly only; pattern left blank */]> { let Inst{23-20} = 0b0010; let Inst{7-4} = 0b0000; } -// FIXME: mask is ignored for the time being. -def MSRi : ABI<0b0011,(outs),(ins so_imm:$a), NoItinerary, "msr", "\tcpsr, $a", +def MSRi : ABI<0b0011, (outs), (ins so_imm:$a, i32imm:$mask), NoItinerary,"msr", + "\tcpsr${mask:msr}, $a", [/* For disassembly only; pattern left blank */]> { let Inst{23-20} = 0b0010; let Inst{7-4} = 0b0000; } -// FIXME: mask is ignored for the time being. -def MSRsys : ABI<0b0001,(outs),(ins GPR:$src),NoItinerary,"msr","\tspsr, $src", +def MSRsys : ABI<0b0001, (outs), (ins GPR:$src, i32imm:$mask),NoItinerary,"msr", + "\tspsr${mask:msr}, $src", [/* For disassembly only; pattern left blank */]> { let Inst{23-20} = 0b0110; let Inst{7-4} = 0b0000; } -// FIXME: mask is ignored for the time being. -def MSRsysi : ABI<0b0011,(outs),(ins so_imm:$a),NoItinerary,"msr","\tspsr, $a", +def MSRsysi : ABI<0b0011,(outs),(ins so_imm:$a, i32imm:$mask),NoItinerary,"msr", + "\tspsr${mask:msr}, $a", [/* For disassembly only; pattern left blank */]> { let Inst{23-20} = 0b0110; let Inst{7-4} = 0b0000; diff --git a/lib/Target/ARM/ARMInstrNEON.td b/lib/Target/ARM/ARMInstrNEON.td index 3aa0810..7c44a2f 100644 --- a/lib/Target/ARM/ARMInstrNEON.td +++ b/lib/Target/ARM/ARMInstrNEON.td @@ -2707,21 +2707,21 @@ def VSETLNi32 : NVSetLane<{1,1,1,0,0,0,?,0}, 0b1011, 0b00, (outs DPR:$dst), } def : Pat<(vector_insert (v16i8 QPR:$src1), GPR:$src2, imm:$lane), (v16i8 (INSERT_SUBREG QPR:$src1, - (VSETLNi8 (v8i8 (EXTRACT_SUBREG QPR:$src1, + (v8i8 (VSETLNi8 (v8i8 (EXTRACT_SUBREG QPR:$src1, (DSubReg_i8_reg imm:$lane))), - GPR:$src2, (SubReg_i8_lane imm:$lane)), + GPR:$src2, (SubReg_i8_lane imm:$lane))), (DSubReg_i8_reg imm:$lane)))>; def : Pat<(vector_insert (v8i16 QPR:$src1), GPR:$src2, imm:$lane), (v8i16 (INSERT_SUBREG QPR:$src1, - (VSETLNi16 (v4i16 (EXTRACT_SUBREG QPR:$src1, + (v4i16 (VSETLNi16 (v4i16 (EXTRACT_SUBREG QPR:$src1, (DSubReg_i16_reg imm:$lane))), - GPR:$src2, (SubReg_i16_lane imm:$lane)), + GPR:$src2, (SubReg_i16_lane imm:$lane))), (DSubReg_i16_reg imm:$lane)))>; def : Pat<(insertelt (v4i32 QPR:$src1), GPR:$src2, imm:$lane), (v4i32 (INSERT_SUBREG QPR:$src1, - (VSETLNi32 (v2i32 (EXTRACT_SUBREG QPR:$src1, + (v2i32 (VSETLNi32 (v2i32 (EXTRACT_SUBREG QPR:$src1, (DSubReg_i32_reg imm:$lane))), - GPR:$src2, (SubReg_i32_lane imm:$lane)), + GPR:$src2, (SubReg_i32_lane imm:$lane))), (DSubReg_i32_reg imm:$lane)))>; def : Pat<(v2f32 (insertelt DPR:$src1, SPR:$src2, imm:$src3)), @@ -3093,16 +3093,17 @@ def VTBX4 class N2VSPat<SDNode OpNode, ValueType ResTy, ValueType OpTy, NeonI Inst> : NEONFPPat<(ResTy (OpNode SPR:$a)), - (EXTRACT_SUBREG (Inst (INSERT_SUBREG (OpTy (IMPLICIT_DEF)), - SPR:$a, arm_ssubreg_0)), + (EXTRACT_SUBREG (OpTy (Inst (INSERT_SUBREG (OpTy (IMPLICIT_DEF)), + SPR:$a, arm_ssubreg_0))), arm_ssubreg_0)>; class N3VSPat<SDNode OpNode, NeonI Inst> : NEONFPPat<(f32 (OpNode SPR:$a, SPR:$b)), - (EXTRACT_SUBREG (Inst (INSERT_SUBREG (v2f32 (IMPLICIT_DEF)), - SPR:$a, arm_ssubreg_0), - (INSERT_SUBREG (v2f32 (IMPLICIT_DEF)), - SPR:$b, arm_ssubreg_0)), + (EXTRACT_SUBREG (v2f32 + (Inst (INSERT_SUBREG (v2f32 (IMPLICIT_DEF)), + SPR:$a, arm_ssubreg_0), + (INSERT_SUBREG (v2f32 (IMPLICIT_DEF)), + SPR:$b, arm_ssubreg_0))), arm_ssubreg_0)>; class N3VSMulOpPat<SDNode MulNode, SDNode OpNode, NeonI Inst> diff --git a/lib/Target/ARM/ARMInstrThumb2.td b/lib/Target/ARM/ARMInstrThumb2.td index 6241766..2fc7d2f 100644 --- a/lib/Target/ARM/ARMInstrThumb2.td +++ b/lib/Target/ARM/ARMInstrThumb2.td @@ -331,9 +331,9 @@ multiclass T2I_bin_ii12rs<bits<3> op23_21, string opc, PatFrag opnode, let Inst{15} = 0; } // 12-bit imm - def ri12 : T2sI<(outs GPR:$dst), (ins GPR:$lhs, imm0_4095:$rhs), IIC_iALUi, - !strconcat(opc, "w"), "\t$dst, $lhs, $rhs", - [(set GPR:$dst, (opnode GPR:$lhs, imm0_4095:$rhs))]> { + def ri12 : T2I<(outs GPR:$dst), (ins GPR:$lhs, imm0_4095:$rhs), IIC_iALUi, + !strconcat(opc, "w"), "\t$dst, $lhs, $rhs", + [(set GPR:$dst, (opnode GPR:$lhs, imm0_4095:$rhs))]> { let Inst{31-27} = 0b11110; let Inst{25} = 1; let Inst{24} = 0; @@ -2637,9 +2637,9 @@ def t2MRSsys : T2I<(outs GPR:$dst), (ins), NoItinerary, "mrs", "\t$dst, spsr", let Inst{12} = 0; } -// FIXME: mask is ignored for the time being. // Rn = Inst{19-16} -def t2MSR : T2I<(outs), (ins GPR:$src), NoItinerary, "msr", "\tcpsr, $src", +def t2MSR : T2I<(outs), (ins GPR:$src, i32imm:$mask), NoItinerary, "msr", + "\tcpsr${mask:msr}, $src", [/* For disassembly only; pattern left blank */]> { let Inst{31-27} = 0b11110; let Inst{26} = 0; @@ -2649,9 +2649,9 @@ def t2MSR : T2I<(outs), (ins GPR:$src), NoItinerary, "msr", "\tcpsr, $src", let Inst{12} = 0; } -// FIXME: mask is ignored for the time being. // Rn = Inst{19-16} -def t2MSRsys : T2I<(outs), (ins GPR:$src), NoItinerary, "msr", "\tspsr, $src", +def t2MSRsys : T2I<(outs), (ins GPR:$src, i32imm:$mask), NoItinerary, "msr", + "\tspsr${mask:msr}, $src", [/* For disassembly only; pattern left blank */]> { let Inst{31-27} = 0b11110; let Inst{26} = 0; diff --git a/lib/Target/ARM/ARMInstrVFP.td b/lib/Target/ARM/ARMInstrVFP.td index 7c117ed..cad24c4 100644 --- a/lib/Target/ARM/ARMInstrVFP.td +++ b/lib/Target/ARM/ARMInstrVFP.td @@ -57,7 +57,7 @@ def vfp_f64imm : Operand<f64>, let canFoldAsLoad = 1, isReMaterializable = 1 in { def VLDRD : ADI5<0b1101, 0b01, (outs DPR:$dst), (ins addrmode5:$addr), IIC_fpLoad64, "vldr", ".64\t$dst, $addr", - [(set DPR:$dst, (load addrmode5:$addr))]>; + [(set DPR:$dst, (f64 (load addrmode5:$addr)))]>; def VLDRS : ASI5<0b1101, 0b01, (outs SPR:$dst), (ins addrmode5:$addr), IIC_fpLoad32, "vldr", ".32\t$dst, $addr", @@ -66,7 +66,7 @@ def VLDRS : ASI5<0b1101, 0b01, (outs SPR:$dst), (ins addrmode5:$addr), def VSTRD : ADI5<0b1101, 0b00, (outs), (ins DPR:$src, addrmode5:$addr), IIC_fpStore64, "vstr", ".64\t$src, $addr", - [(store DPR:$src, addrmode5:$addr)]>; + [(store (f64 DPR:$src), addrmode5:$addr)]>; def VSTRS : ASI5<0b1101, 0b00, (outs), (ins SPR:$src, addrmode5:$addr), IIC_fpStore32, "vstr", ".32\t$src, $addr", @@ -116,7 +116,7 @@ def VSTMS : AXSI5<(outs), (ins addrmode5:$addr, pred:$p, reglist:$wb, def VADDD : ADbI<0b11100, 0b11, 0, 0, (outs DPR:$dst), (ins DPR:$a, DPR:$b), IIC_fpALU64, "vadd", ".f64\t$dst, $a, $b", - [(set DPR:$dst, (fadd DPR:$a, DPR:$b))]>; + [(set DPR:$dst, (fadd DPR:$a, (f64 DPR:$b)))]>; def VADDS : ASbIn<0b11100, 0b11, 0, 0, (outs SPR:$dst), (ins SPR:$a, SPR:$b), IIC_fpALU32, "vadd", ".f32\t$dst, $a, $b", @@ -126,7 +126,7 @@ def VADDS : ASbIn<0b11100, 0b11, 0, 0, (outs SPR:$dst), (ins SPR:$a, SPR:$b), let Defs = [FPSCR] in { def VCMPED : ADuI<0b11101, 0b11, 0b0100, 0b11, 0, (outs), (ins DPR:$a, DPR:$b), IIC_fpCMP64, "vcmpe", ".f64\t$a, $b", - [(arm_cmpfp DPR:$a, DPR:$b)]>; + [(arm_cmpfp DPR:$a, (f64 DPR:$b))]>; def VCMPD : ADuI<0b11101, 0b11, 0b0100, 0b01, 0, (outs), (ins DPR:$a, DPR:$b), IIC_fpCMP64, "vcmp", ".f64\t$a, $b", @@ -143,7 +143,7 @@ def VCMPS : ASuI<0b11101, 0b11, 0b0100, 0b01, 0, (outs), (ins SPR:$a, SPR:$b), def VDIVD : ADbI<0b11101, 0b00, 0, 0, (outs DPR:$dst), (ins DPR:$a, DPR:$b), IIC_fpDIV64, "vdiv", ".f64\t$dst, $a, $b", - [(set DPR:$dst, (fdiv DPR:$a, DPR:$b))]>; + [(set DPR:$dst, (fdiv DPR:$a, (f64 DPR:$b)))]>; def VDIVS : ASbI<0b11101, 0b00, 0, 0, (outs SPR:$dst), (ins SPR:$a, SPR:$b), IIC_fpDIV32, "vdiv", ".f32\t$dst, $a, $b", @@ -151,7 +151,7 @@ def VDIVS : ASbI<0b11101, 0b00, 0, 0, (outs SPR:$dst), (ins SPR:$a, SPR:$b), def VMULD : ADbI<0b11100, 0b10, 0, 0, (outs DPR:$dst), (ins DPR:$a, DPR:$b), IIC_fpMUL64, "vmul", ".f64\t$dst, $a, $b", - [(set DPR:$dst, (fmul DPR:$a, DPR:$b))]>; + [(set DPR:$dst, (fmul DPR:$a, (f64 DPR:$b)))]>; def VMULS : ASbIn<0b11100, 0b10, 0, 0, (outs SPR:$dst), (ins SPR:$a, SPR:$b), IIC_fpMUL32, "vmul", ".f32\t$dst, $a, $b", @@ -159,14 +159,14 @@ def VMULS : ASbIn<0b11100, 0b10, 0, 0, (outs SPR:$dst), (ins SPR:$a, SPR:$b), def VNMULD : ADbI<0b11100, 0b10, 1, 0, (outs DPR:$dst), (ins DPR:$a, DPR:$b), IIC_fpMUL64, "vnmul", ".f64\t$dst, $a, $b", - [(set DPR:$dst, (fneg (fmul DPR:$a, DPR:$b)))]>; + [(set DPR:$dst, (fneg (fmul DPR:$a, (f64 DPR:$b))))]>; def VNMULS : ASbI<0b11100, 0b10, 1, 0, (outs SPR:$dst), (ins SPR:$a, SPR:$b), IIC_fpMUL32, "vnmul", ".f32\t$dst, $a, $b", [(set SPR:$dst, (fneg (fmul SPR:$a, SPR:$b)))]>; // Match reassociated forms only if not sign dependent rounding. -def : Pat<(fmul (fneg DPR:$a), DPR:$b), +def : Pat<(fmul (fneg DPR:$a), (f64 DPR:$b)), (VNMULD DPR:$a, DPR:$b)>, Requires<[NoHonorSignDependentRounding]>; def : Pat<(fmul (fneg SPR:$a), SPR:$b), (VNMULS SPR:$a, SPR:$b)>, Requires<[NoHonorSignDependentRounding]>; @@ -174,7 +174,7 @@ def : Pat<(fmul (fneg SPR:$a), SPR:$b), def VSUBD : ADbI<0b11100, 0b11, 1, 0, (outs DPR:$dst), (ins DPR:$a, DPR:$b), IIC_fpALU64, "vsub", ".f64\t$dst, $a, $b", - [(set DPR:$dst, (fsub DPR:$a, DPR:$b))]>; + [(set DPR:$dst, (fsub DPR:$a, (f64 DPR:$b)))]>; def VSUBS : ASbIn<0b11100, 0b11, 1, 0, (outs SPR:$dst), (ins SPR:$a, SPR:$b), IIC_fpALU32, "vsub", ".f32\t$dst, $a, $b", @@ -186,7 +186,7 @@ def VSUBS : ASbIn<0b11100, 0b11, 1, 0, (outs SPR:$dst), (ins SPR:$a, SPR:$b), def VABSD : ADuI<0b11101, 0b11, 0b0000, 0b11, 0, (outs DPR:$dst), (ins DPR:$a), IIC_fpUNA64, "vabs", ".f64\t$dst, $a", - [(set DPR:$dst, (fabs DPR:$a))]>; + [(set DPR:$dst, (fabs (f64 DPR:$a)))]>; def VABSS : ASuIn<0b11101, 0b11, 0b0000, 0b11, 0,(outs SPR:$dst), (ins SPR:$a), IIC_fpUNA32, "vabs", ".f32\t$dst, $a", @@ -195,7 +195,7 @@ def VABSS : ASuIn<0b11101, 0b11, 0b0000, 0b11, 0,(outs SPR:$dst), (ins SPR:$a), let Defs = [FPSCR] in { def VCMPEZD : ADuI<0b11101, 0b11, 0b0101, 0b11, 0, (outs), (ins DPR:$a), IIC_fpCMP64, "vcmpe", ".f64\t$a, #0", - [(arm_cmpfp0 DPR:$a)]>; + [(arm_cmpfp0 (f64 DPR:$a))]>; def VCMPZD : ADuI<0b11101, 0b11, 0b0101, 0b01, 0, (outs), (ins DPR:$a), IIC_fpCMP64, "vcmp", ".f64\t$a, #0", @@ -253,7 +253,7 @@ def VMOVS: ASuI<0b11101, 0b11, 0b0000, 0b01, 0, (outs SPR:$dst), (ins SPR:$a), def VNEGD : ADuI<0b11101, 0b11, 0b0001, 0b01, 0, (outs DPR:$dst), (ins DPR:$a), IIC_fpUNA64, "vneg", ".f64\t$dst, $a", - [(set DPR:$dst, (fneg DPR:$a))]>; + [(set DPR:$dst, (fneg (f64 DPR:$a)))]>; def VNEGS : ASuIn<0b11101, 0b11, 0b0001, 0b01, 0,(outs SPR:$dst), (ins SPR:$a), IIC_fpUNA32, "vneg", ".f32\t$dst, $a", @@ -261,7 +261,7 @@ def VNEGS : ASuIn<0b11101, 0b11, 0b0001, 0b01, 0,(outs SPR:$dst), (ins SPR:$a), def VSQRTD : ADuI<0b11101, 0b11, 0b0001, 0b11, 0, (outs DPR:$dst), (ins DPR:$a), IIC_fpSQRT64, "vsqrt", ".f64\t$dst, $a", - [(set DPR:$dst, (fsqrt DPR:$a))]>; + [(set DPR:$dst, (fsqrt (f64 DPR:$a)))]>; def VSQRTS : ASuI<0b11101, 0b11, 0b0001, 0b11, 0, (outs SPR:$dst), (ins SPR:$a), IIC_fpSQRT32, "vsqrt", ".f32\t$dst, $a", @@ -325,7 +325,7 @@ def VMOVSRR : AVConv5I<0b11000100, 0b1010, def VSITOD : AVConv1I<0b11101, 0b11, 0b1000, 0b1011, (outs DPR:$dst), (ins SPR:$a), IIC_fpCVTID, "vcvt", ".f64.s32\t$dst, $a", - [(set DPR:$dst, (arm_sitof SPR:$a))]> { + [(set DPR:$dst, (f64 (arm_sitof SPR:$a)))]> { let Inst{7} = 1; // s32 } @@ -339,7 +339,7 @@ def VSITOS : AVConv1In<0b11101, 0b11, 0b1000, 0b1010, def VUITOD : AVConv1I<0b11101, 0b11, 0b1000, 0b1011, (outs DPR:$dst), (ins SPR:$a), IIC_fpCVTID, "vcvt", ".f64.u32\t$dst, $a", - [(set DPR:$dst, (arm_uitof SPR:$a))]> { + [(set DPR:$dst, (f64 (arm_uitof SPR:$a)))]> { let Inst{7} = 0; // u32 } @@ -356,7 +356,7 @@ def VUITOS : AVConv1In<0b11101, 0b11, 0b1000, 0b1010, def VTOSIZD : AVConv1I<0b11101, 0b11, 0b1101, 0b1011, (outs SPR:$dst), (ins DPR:$a), IIC_fpCVTDI, "vcvt", ".s32.f64\t$dst, $a", - [(set SPR:$dst, (arm_ftosi DPR:$a))]> { + [(set SPR:$dst, (arm_ftosi (f64 DPR:$a)))]> { let Inst{7} = 1; // Z bit } @@ -370,7 +370,7 @@ def VTOSIZS : AVConv1In<0b11101, 0b11, 0b1101, 0b1010, def VTOUIZD : AVConv1I<0b11101, 0b11, 0b1100, 0b1011, (outs SPR:$dst), (ins DPR:$a), IIC_fpCVTDI, "vcvt", ".u32.f64\t$dst, $a", - [(set SPR:$dst, (arm_ftoui DPR:$a))]> { + [(set SPR:$dst, (arm_ftoui (f64 DPR:$a)))]> { let Inst{7} = 1; // Z bit } @@ -514,7 +514,8 @@ def VULTOD : AVConv1XI<0b11101, 0b11, 0b1011, 0b1011, 1, def VMLAD : ADbI<0b11100, 0b00, 0, 0, (outs DPR:$dst), (ins DPR:$dstin, DPR:$a, DPR:$b), IIC_fpMAC64, "vmla", ".f64\t$dst, $a, $b", - [(set DPR:$dst, (fadd (fmul DPR:$a, DPR:$b), DPR:$dstin))]>, + [(set DPR:$dst, (fadd (fmul DPR:$a, DPR:$b), + (f64 DPR:$dstin)))]>, RegConstraint<"$dstin = $dst">; def VMLAS : ASbIn<0b11100, 0b00, 0, 0, @@ -526,7 +527,8 @@ def VMLAS : ASbIn<0b11100, 0b00, 0, 0, def VNMLSD : ADbI<0b11100, 0b01, 0, 0, (outs DPR:$dst), (ins DPR:$dstin, DPR:$a, DPR:$b), IIC_fpMAC64, "vnmls", ".f64\t$dst, $a, $b", - [(set DPR:$dst, (fsub (fmul DPR:$a, DPR:$b), DPR:$dstin))]>, + [(set DPR:$dst, (fsub (fmul DPR:$a, DPR:$b), + (f64 DPR:$dstin)))]>, RegConstraint<"$dstin = $dst">; def VNMLSS : ASbI<0b11100, 0b01, 0, 0, @@ -538,7 +540,8 @@ def VNMLSS : ASbI<0b11100, 0b01, 0, 0, def VMLSD : ADbI<0b11100, 0b00, 1, 0, (outs DPR:$dst), (ins DPR:$dstin, DPR:$a, DPR:$b), IIC_fpMAC64, "vmls", ".f64\t$dst, $a, $b", - [(set DPR:$dst, (fadd (fneg (fmul DPR:$a, DPR:$b)), DPR:$dstin))]>, + [(set DPR:$dst, (fadd (fneg (fmul DPR:$a, DPR:$b)), + (f64 DPR:$dstin)))]>, RegConstraint<"$dstin = $dst">; def VMLSS : ASbIn<0b11100, 0b00, 1, 0, @@ -547,7 +550,7 @@ def VMLSS : ASbIn<0b11100, 0b00, 1, 0, [(set SPR:$dst, (fadd (fneg (fmul SPR:$a, SPR:$b)), SPR:$dstin))]>, RegConstraint<"$dstin = $dst">; -def : Pat<(fsub DPR:$dstin, (fmul DPR:$a, DPR:$b)), +def : Pat<(fsub DPR:$dstin, (fmul DPR:$a, (f64 DPR:$b))), (VMLSD DPR:$dstin, DPR:$a, DPR:$b)>, Requires<[DontUseNEONForFP]>; def : Pat<(fsub SPR:$dstin, (fmul SPR:$a, SPR:$b)), (VMLSS SPR:$dstin, SPR:$a, SPR:$b)>, Requires<[DontUseNEONForFP]>; @@ -555,7 +558,8 @@ def : Pat<(fsub SPR:$dstin, (fmul SPR:$a, SPR:$b)), def VNMLAD : ADbI<0b11100, 0b01, 1, 0, (outs DPR:$dst), (ins DPR:$dstin, DPR:$a, DPR:$b), IIC_fpMAC64, "vnmla", ".f64\t$dst, $a, $b", - [(set DPR:$dst, (fsub (fneg (fmul DPR:$a, DPR:$b)), DPR:$dstin))]>, + [(set DPR:$dst, (fsub (fneg (fmul DPR:$a, DPR:$b)), + (f64 DPR:$dstin)))]>, RegConstraint<"$dstin = $dst">; def VNMLAS : ASbI<0b11100, 0b01, 1, 0, diff --git a/lib/Target/ARM/ARMMCAsmInfo.cpp b/lib/Target/ARM/ARMMCAsmInfo.cpp index ccd6add..20197e4 100644 --- a/lib/Target/ARM/ARMMCAsmInfo.cpp +++ b/lib/Target/ARM/ARMMCAsmInfo.cpp @@ -48,7 +48,6 @@ ARMMCAsmInfoDarwin::ARMMCAsmInfoDarwin() { // Exceptions handling ExceptionsType = ExceptionHandling::SjLj; - AbsoluteEHSectionOffsets = false; } ARMELFMCAsmInfo::ARMELFMCAsmInfo() { diff --git a/lib/Target/ARM/ARMSubtarget.cpp b/lib/Target/ARM/ARMSubtarget.cpp index 426862c..622034b 100644 --- a/lib/Target/ARM/ARMSubtarget.cpp +++ b/lib/Target/ARM/ARMSubtarget.cpp @@ -33,7 +33,7 @@ UseMOVT("arm-use-movt", ARMSubtarget::ARMSubtarget(const std::string &TT, const std::string &FS, bool isT) - : ARMArchVersion(V4T) + : ARMArchVersion(V4) , ARMFPUType(None) , UseNEONForSinglePrecisionFP(UseNEONFP) , IsThumb(isT) @@ -54,6 +54,11 @@ ARMSubtarget::ARMSubtarget(const std::string &TT, const std::string &FS, // Parse features string. CPUString = ParseSubtargetFeatures(FS, CPUString); + // When no arch is specified either by CPU or by attributes, make the default + // ARMv4T. + if (CPUString == "generic" && (FS.empty() || FS == "generic")) + ARMArchVersion = V4T; + // Set the boolean corresponding to the current target triple, or the default // if one cannot be determined, to true. unsigned Len = TT.length(); @@ -68,25 +73,28 @@ ARMSubtarget::ARMSubtarget(const std::string &TT, const std::string &FS, } if (Idx) { unsigned SubVer = TT[Idx]; - if (SubVer > '4' && SubVer <= '9') { - if (SubVer >= '7') { - ARMArchVersion = V7A; - } else if (SubVer == '6') { - ARMArchVersion = V6; - if (Len >= Idx+3 && TT[Idx+1] == 't' && TT[Idx+2] == '2') - ARMArchVersion = V6T2; - } else if (SubVer == '5') { - ARMArchVersion = V5T; - if (Len >= Idx+3 && TT[Idx+1] == 't' && TT[Idx+2] == 'e') - ARMArchVersion = V5TE; - } - if (ARMArchVersion >= V6T2) - ThumbMode = Thumb2; + if (SubVer >= '7' && SubVer <= '9') { + ARMArchVersion = V7A; + } else if (SubVer == '6') { + ARMArchVersion = V6; + if (Len >= Idx+3 && TT[Idx+1] == 't' && TT[Idx+2] == '2') + ARMArchVersion = V6T2; + } else if (SubVer == '5') { + ARMArchVersion = V5T; + if (Len >= Idx+3 && TT[Idx+1] == 't' && TT[Idx+2] == 'e') + ARMArchVersion = V5TE; + } else if (SubVer == '4') { + if (Len >= Idx+2 && TT[Idx+1] == 't') + ARMArchVersion = V4T; + else + ARMArchVersion = V4; } } // Thumb2 implies at least V6T2. - if (ARMArchVersion < V6T2 && ThumbMode >= Thumb2) + if (ARMArchVersion >= V6T2) + ThumbMode = Thumb2; + else if (ThumbMode >= Thumb2) ARMArchVersion = V6T2; if (Len >= 10) { diff --git a/lib/Target/ARM/ARMSubtarget.h b/lib/Target/ARM/ARMSubtarget.h index 3f06b7b..6980851 100644 --- a/lib/Target/ARM/ARMSubtarget.h +++ b/lib/Target/ARM/ARMSubtarget.h @@ -26,7 +26,7 @@ class GlobalValue; class ARMSubtarget : public TargetSubtarget { protected: enum ARMArchEnum { - V4T, V5T, V5TE, V6, V6T2, V7A + V4, V4T, V5T, V5TE, V6, V6T2, V7A }; enum ARMFPEnum { @@ -38,7 +38,7 @@ protected: Thumb2 }; - /// ARMArchVersion - ARM architecture version: V4T (base), V5T, V5TE, + /// ARMArchVersion - ARM architecture version: V4, V4T (base), V5T, V5TE, /// V6, V6T2, V7A. ARMArchEnum ARMArchVersion; diff --git a/lib/Target/ARM/ARMTargetObjectFile.cpp b/lib/Target/ARM/ARMTargetObjectFile.cpp new file mode 100644 index 0000000..7463e30 --- /dev/null +++ b/lib/Target/ARM/ARMTargetObjectFile.cpp @@ -0,0 +1,54 @@ +//===-- llvm/Target/ARMTargetObjectFile.cpp - ARM Object Info Impl --------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "ARMTargetObjectFile.h" +#include "ARMSubtarget.h" +#include "llvm/MC/MCSectionELF.h" +#include "llvm/MC/MCSectionMachO.h" +#include "llvm/Support/Dwarf.h" +#include "llvm/Target/TargetMachine.h" +using namespace llvm; +using namespace dwarf; + +//===----------------------------------------------------------------------===// +// ELF Target +//===----------------------------------------------------------------------===// + +void ARMElfTargetObjectFile::Initialize(MCContext &Ctx, + const TargetMachine &TM) { + TargetLoweringObjectFileELF::Initialize(Ctx, TM); + + if (TM.getSubtarget<ARMSubtarget>().isAAPCS_ABI()) { + StaticCtorSection = + getELFSection(".init_array", MCSectionELF::SHT_INIT_ARRAY, + MCSectionELF::SHF_WRITE | MCSectionELF::SHF_ALLOC, + SectionKind::getDataRel()); + StaticDtorSection = + getELFSection(".fini_array", MCSectionELF::SHT_FINI_ARRAY, + MCSectionELF::SHF_WRITE | MCSectionELF::SHF_ALLOC, + SectionKind::getDataRel()); + } +} + +//===----------------------------------------------------------------------===// +// Mach-O Target +//===----------------------------------------------------------------------===// + +void ARMMachOTargetObjectFile::Initialize(MCContext &Ctx, + const TargetMachine &TM) { + TargetLoweringObjectFileMachO::Initialize(Ctx, TM); + + // Exception Handling. + LSDASection = getMachOSection("__TEXT", "__gcc_except_tab", 0, + SectionKind::getReadOnlyWithRel()); +} + +unsigned ARMMachOTargetObjectFile::getTTypeEncoding() const { + return DW_EH_PE_indirect | DW_EH_PE_pcrel | DW_EH_PE_sdata4; +} diff --git a/lib/Target/ARM/ARMTargetObjectFile.h b/lib/Target/ARM/ARMTargetObjectFile.h index a488c0a..481d7ab 100644 --- a/lib/Target/ARM/ARMTargetObjectFile.h +++ b/lib/Target/ARM/ARMTargetObjectFile.h @@ -11,29 +11,31 @@ #define LLVM_TARGET_ARM_TARGETOBJECTFILE_H #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" -#include "llvm/MC/MCSectionELF.h" namespace llvm { - class ARMElfTargetObjectFile : public TargetLoweringObjectFileELF { - public: - ARMElfTargetObjectFile() : TargetLoweringObjectFileELF() {} - - void Initialize(MCContext &Ctx, const TargetMachine &TM) { - TargetLoweringObjectFileELF::Initialize(Ctx, TM); - - if (TM.getSubtarget<ARMSubtarget>().isAAPCS_ABI()) { - StaticCtorSection = - getELFSection(".init_array", MCSectionELF::SHT_INIT_ARRAY, - MCSectionELF::SHF_WRITE | MCSectionELF::SHF_ALLOC, - SectionKind::getDataRel()); - StaticDtorSection = - getELFSection(".fini_array", MCSectionELF::SHT_FINI_ARRAY, - MCSectionELF::SHF_WRITE | MCSectionELF::SHF_ALLOC, - SectionKind::getDataRel()); - } - } - }; +class MCContext; +class TargetMachine; + +class ARMElfTargetObjectFile : public TargetLoweringObjectFileELF { +public: + ARMElfTargetObjectFile() : TargetLoweringObjectFileELF() {} + + virtual void Initialize(MCContext &Ctx, const TargetMachine &TM); +}; + +// FIXME: This subclass isn't 100% necessary. It will become obsolete once we +// can place all LSDAs into the TEXT section. See +// <rdar://problem/6804645>. +class ARMMachOTargetObjectFile : public TargetLoweringObjectFileMachO { +public: + ARMMachOTargetObjectFile() : TargetLoweringObjectFileMachO() {} + + virtual void Initialize(MCContext &Ctx, const TargetMachine &TM); + + virtual unsigned getTTypeEncoding() const; +}; + } // end namespace llvm #endif diff --git a/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp b/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp index d6d595c..314114c 100644 --- a/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp +++ b/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp @@ -33,6 +33,7 @@ #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCContext.h" +#include "llvm/MC/MCExpr.h" #include "llvm/MC/MCInst.h" #include "llvm/MC/MCSectionMachO.h" #include "llvm/MC/MCStreamer.h" @@ -848,7 +849,7 @@ GetARMSetPICJumpTableLabel2(unsigned uid, unsigned uid2, raw_svector_ostream(Name) << MAI->getPrivateGlobalPrefix() << getFunctionNumber() << '_' << uid << '_' << uid2 << "_set_" << MBB->getNumber(); - return OutContext.GetOrCreateSymbol(Name.str()); + return OutContext.GetOrCreateTemporarySymbol(Name.str()); } MCSymbol *ARMAsmPrinter:: @@ -856,7 +857,7 @@ GetARMJTIPICJumpTableLabel2(unsigned uid, unsigned uid2) const { SmallString<60> Name; raw_svector_ostream(Name) << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() << '_' << uid << '_' << uid2; - return OutContext.GetOrCreateSymbol(Name.str()); + return OutContext.GetOrCreateTemporarySymbol(Name.str()); } void ARMAsmPrinter::printJTBlockOperand(const MachineInstr *MI, int OpNum) { @@ -1128,17 +1129,40 @@ void ARMAsmPrinter::EmitEndOfAsmFile(Module &M) { OutStreamer.SwitchSection(TLOFMacho.getNonLazySymbolPointerSection()); EmitAlignment(2); for (unsigned i = 0, e = Stubs.size(); i != e; ++i) { - O << *Stubs[i].first << ":\n\t.indirect_symbol "; - O << *Stubs[i].second << "\n\t.long\t0\n"; + // L_foo$stub: + OutStreamer.EmitLabel(Stubs[i].first); + // .indirect_symbol _foo + MCSymbol *MCSym = Stubs[i].second; + OutStreamer.EmitSymbolAttribute(MCSym, MCSA_IndirectSymbol); + + if (MCSym->isUndefined()) + // External to current translation unit. + OutStreamer.EmitIntValue(0, 4/*size*/, 0/*addrspace*/); + else + // Internal to current translation unit. + OutStreamer.EmitValue(MCSymbolRefExpr::Create(MCSym, OutContext), + 4/*size*/, 0/*addrspace*/); } + + Stubs.clear(); + OutStreamer.AddBlankLine(); } Stubs = MMIMacho.GetHiddenGVStubList(); if (!Stubs.empty()) { OutStreamer.SwitchSection(getObjFileLowering().getDataSection()); EmitAlignment(2); - for (unsigned i = 0, e = Stubs.size(); i != e; ++i) - O << *Stubs[i].first << ":\n\t.long " << *Stubs[i].second << "\n"; + for (unsigned i = 0, e = Stubs.size(); i != e; ++i) { + // L_foo$stub: + OutStreamer.EmitLabel(Stubs[i].first); + // .long _foo + OutStreamer.EmitValue(MCSymbolRefExpr::Create(Stubs[i].second, + OutContext), + 4/*size*/, 0/*addrspace*/); + } + + Stubs.clear(); + OutStreamer.AddBlankLine(); } // Funny Darwin hack: This flag tells the linker that no global symbols @@ -1168,7 +1192,7 @@ void ARMAsmPrinter::printInstructionThroughMCStreamer(const MachineInstr *MI) { // FIXME: MOVE TO SHARED PLACE. unsigned Id = (unsigned)MI->getOperand(2).getImm(); const char *Prefix = MAI->getPrivateGlobalPrefix(); - MCSymbol *Label =OutContext.GetOrCreateSymbol(Twine(Prefix) + MCSymbol *Label =OutContext.GetOrCreateTemporarySymbol(Twine(Prefix) + "PC" + Twine(getFunctionNumber()) + "_" + Twine(Id)); OutStreamer.EmitLabel(Label); diff --git a/lib/Target/ARM/AsmPrinter/ARMMCInstLower.cpp b/lib/Target/ARM/AsmPrinter/ARMMCInstLower.cpp index 1b2dd48..5f8705e 100644 --- a/lib/Target/ARM/AsmPrinter/ARMMCInstLower.cpp +++ b/lib/Target/ARM/AsmPrinter/ARMMCInstLower.cpp @@ -74,7 +74,7 @@ GetJumpTableSymbol(const MachineOperand &MO) const { #endif // Create a symbol for the name. - return Ctx.GetOrCreateSymbol(Name.str()); + return Ctx.GetOrCreateTemporarySymbol(Name.str()); } MCSymbol *ARMMCInstLower:: @@ -90,7 +90,7 @@ GetConstantPoolIndexSymbol(const MachineOperand &MO) const { #endif // Create a symbol for the name. - return Ctx.GetOrCreateSymbol(Name.str()); + return Ctx.GetOrCreateTemporarySymbol(Name.str()); } MCOperand ARMMCInstLower:: diff --git a/lib/Target/ARM/CMakeLists.txt b/lib/Target/ARM/CMakeLists.txt index 964551f..bbc0095 100644 --- a/lib/Target/ARM/CMakeLists.txt +++ b/lib/Target/ARM/CMakeLists.txt @@ -27,6 +27,7 @@ add_llvm_target(ARMCodeGen ARMRegisterInfo.cpp ARMSubtarget.cpp ARMTargetMachine.cpp + ARMTargetObjectFile.cpp NEONMoveFix.cpp NEONPreAllocPass.cpp Thumb1InstrInfo.cpp diff --git a/lib/Target/ARM/Thumb1RegisterInfo.cpp b/lib/Target/ARM/Thumb1RegisterInfo.cpp index 163d1e9..6215d2f 100644 --- a/lib/Target/ARM/Thumb1RegisterInfo.cpp +++ b/lib/Target/ARM/Thumb1RegisterInfo.cpp @@ -33,10 +33,13 @@ #include "llvm/Target/TargetMachine.h" #include "llvm/ADT/BitVector.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/Support/CommandLine.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; +extern cl::opt<bool> ReuseFrameIndexVals; + Thumb1RegisterInfo::Thumb1RegisterInfo(const ARMBaseInstrInfo &tii, const ARMSubtarget &sti) : ARMBaseRegisterInfo(tii, sti) { @@ -426,7 +429,7 @@ Thumb1RegisterInfo::saveScavengerRegister(MachineBasicBlock &MBB, unsigned Thumb1RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, - int SPAdj, int *Value, + int SPAdj, FrameIndexValue *Value, RegScavenger *RS) const{ unsigned VReg = 0; unsigned i = 0; @@ -638,8 +641,10 @@ Thumb1RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, } else if (Desc.mayStore()) { VReg = MF.getRegInfo().createVirtualRegister(ARM::tGPRRegisterClass); assert (Value && "Frame index virtual allocated, but Value arg is NULL!"); - *Value = Offset; bool UseRR = false; + bool TrackVReg = true; + Value->first = FrameReg; // use the frame register as a kind indicator + Value->second = Offset; if (Opcode == ARM::tSpill) { if (FrameReg == ARM::SP) @@ -648,6 +653,7 @@ Thumb1RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, else { emitLoadConstPool(MBB, II, dl, VReg, 0, Offset); UseRR = true; + TrackVReg = false; } } else emitThumbRegPlusImmediate(MBB, II, VReg, FrameReg, Offset, TII, @@ -658,6 +664,8 @@ Thumb1RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, MI.addOperand(MachineOperand::CreateReg(FrameReg, false)); else // tSTR has an extra register operand. MI.addOperand(MachineOperand::CreateReg(0, false)); + if (!ReuseFrameIndexVals || !TrackVReg) + VReg = 0; } else assert(false && "Unexpected opcode!"); diff --git a/lib/Target/ARM/Thumb1RegisterInfo.h b/lib/Target/ARM/Thumb1RegisterInfo.h index 37ad388..4eca367 100644 --- a/lib/Target/ARM/Thumb1RegisterInfo.h +++ b/lib/Target/ARM/Thumb1RegisterInfo.h @@ -59,7 +59,7 @@ public: const TargetRegisterClass *RC, unsigned Reg) const; unsigned eliminateFrameIndex(MachineBasicBlock::iterator II, - int SPAdj, int *Value = NULL, + int SPAdj, FrameIndexValue *Value = NULL, RegScavenger *RS = NULL) const; void emitPrologue(MachineFunction &MF) const; diff --git a/lib/Target/ARM/Thumb2InstrInfo.cpp b/lib/Target/ARM/Thumb2InstrInfo.cpp index 20f13f1..e4abcdb 100644 --- a/lib/Target/ARM/Thumb2InstrInfo.cpp +++ b/lib/Target/ARM/Thumb2InstrInfo.cpp @@ -164,6 +164,7 @@ void llvm::emitT2RegPlusImmediate(MachineBasicBlock &MBB, continue; } + bool HasCCOut = true; if (BaseReg == ARM::SP) { // sub sp, sp, #imm7 if (DestReg == ARM::SP && (ThisVal < ((1 << 7)-1) * 4)) { @@ -195,6 +196,7 @@ void llvm::emitT2RegPlusImmediate(MachineBasicBlock &MBB, NumBytes = 0; } else if (ThisVal < 4096) { Opc = isSub ? ARM::t2SUBri12 : ARM::t2ADDri12; + HasCCOut = false; NumBytes = 0; } else { // FIXME: Move this to ARMAddressingModes.h? @@ -207,9 +209,12 @@ void llvm::emitT2RegPlusImmediate(MachineBasicBlock &MBB, } // Build the new ADD / SUB. - AddDefaultCC(AddDefaultPred(BuildMI(MBB, MBBI, dl, TII.get(Opc), DestReg) - .addReg(BaseReg, RegState::Kill) - .addImm(ThisVal))); + MachineInstrBuilder MIB = + AddDefaultPred(BuildMI(MBB, MBBI, dl, TII.get(Opc), DestReg) + .addReg(BaseReg, RegState::Kill) + .addImm(ThisVal)); + if (HasCCOut) + AddDefaultCC(MIB); BaseReg = DestReg; } @@ -328,7 +333,6 @@ bool llvm::rewriteT2FrameIndex(MachineInstr &MI, unsigned FrameRegIdx, if (Opcode == ARM::t2ADDri || Opcode == ARM::t2ADDri12) { Offset += MI.getOperand(FrameRegIdx+1).getImm(); - bool isSP = FrameReg == ARM::SP; unsigned PredReg; if (Offset == 0 && getInstrPredicate(&MI, PredReg) == ARMCC::AL) { // Turn it into a move. @@ -342,6 +346,9 @@ bool llvm::rewriteT2FrameIndex(MachineInstr &MI, unsigned FrameRegIdx, return true; } + bool isSP = FrameReg == ARM::SP; + bool HasCCOut = Opcode != ARM::t2ADDri12; + if (Offset < 0) { Offset = -Offset; isSub = true; @@ -354,17 +361,24 @@ bool llvm::rewriteT2FrameIndex(MachineInstr &MI, unsigned FrameRegIdx, if (ARM_AM::getT2SOImmVal(Offset) != -1) { MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false); MI.getOperand(FrameRegIdx+1).ChangeToImmediate(Offset); + // Add cc_out operand if the original instruction did not have one. + if (!HasCCOut) + MI.addOperand(MachineOperand::CreateReg(0, false)); Offset = 0; return true; } // Another common case: imm12. - if (Offset < 4096) { + if (Offset < 4096 && + (!HasCCOut || MI.getOperand(MI.getNumOperands()-1).getReg() == 0)) { unsigned NewOpc = isSP ? (isSub ? ARM::t2SUBrSPi12 : ARM::t2ADDrSPi12) : (isSub ? ARM::t2SUBri12 : ARM::t2ADDri12); MI.setDesc(TII.get(NewOpc)); MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false); MI.getOperand(FrameRegIdx+1).ChangeToImmediate(Offset); + // Remove the cc_out operand. + if (HasCCOut) + MI.RemoveOperand(MI.getNumOperands()-1); Offset = 0; return true; } @@ -380,6 +394,10 @@ bool llvm::rewriteT2FrameIndex(MachineInstr &MI, unsigned FrameRegIdx, assert(ARM_AM::getT2SOImmVal(ThisImmVal) != -1 && "Bit extraction didn't work?"); MI.getOperand(FrameRegIdx+1).ChangeToImmediate(ThisImmVal); + // Add cc_out operand if the original instruction did not have one. + if (!HasCCOut) + MI.addOperand(MachineOperand::CreateReg(0, false)); + } else { // AddrMode4 and AddrMode6 cannot handle any offset. diff --git a/lib/Target/Alpha/AlphaInstrInfo.td b/lib/Target/Alpha/AlphaInstrInfo.td index 341c4a7..95de3d8 100644 --- a/lib/Target/Alpha/AlphaInstrInfo.td +++ b/lib/Target/Alpha/AlphaInstrInfo.td @@ -892,7 +892,7 @@ def : Pat<(brcond (setge GPRC:$RA, 0), bb:$DISP), (COND_BRANCH_I (immBRCond 2), GPRC:$RA, bb:$DISP)>; def : Pat<(brcond (setgt GPRC:$RA, 0), bb:$DISP), (COND_BRANCH_I (immBRCond 3), GPRC:$RA, bb:$DISP)>; -def : Pat<(brcond (and GPRC:$RA, 1), bb:$DISP), +def : Pat<(brcond (and GPRC:$RA, 1), bb:$DISP), (COND_BRANCH_I (immBRCond 6), GPRC:$RA, bb:$DISP)>; def : Pat<(brcond (setle GPRC:$RA, 0), bb:$DISP), (COND_BRANCH_I (immBRCond 4), GPRC:$RA, bb:$DISP)>; diff --git a/lib/Target/Alpha/AlphaRegisterInfo.cpp b/lib/Target/Alpha/AlphaRegisterInfo.cpp index ba662fb..55eec3a 100644 --- a/lib/Target/Alpha/AlphaRegisterInfo.cpp +++ b/lib/Target/Alpha/AlphaRegisterInfo.cpp @@ -153,7 +153,7 @@ eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, unsigned AlphaRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, - int SPAdj, int *Value, + int SPAdj, FrameIndexValue *Value, RegScavenger *RS) const { assert(SPAdj == 0 && "Unexpected"); diff --git a/lib/Target/Alpha/AlphaRegisterInfo.h b/lib/Target/Alpha/AlphaRegisterInfo.h index a971e21..720367a 100644 --- a/lib/Target/Alpha/AlphaRegisterInfo.h +++ b/lib/Target/Alpha/AlphaRegisterInfo.h @@ -42,7 +42,7 @@ struct AlphaRegisterInfo : public AlphaGenRegisterInfo { MachineBasicBlock::iterator I) const; unsigned eliminateFrameIndex(MachineBasicBlock::iterator II, - int SPAdj, int *Value = NULL, + int SPAdj, FrameIndexValue *Value = NULL, RegScavenger *RS = NULL) const; //void processFunctionBeforeFrameFinalized(MachineFunction &MF) const; diff --git a/lib/Target/Blackfin/BlackfinRegisterInfo.cpp b/lib/Target/Blackfin/BlackfinRegisterInfo.cpp index 224165b..b39a342 100644 --- a/lib/Target/Blackfin/BlackfinRegisterInfo.cpp +++ b/lib/Target/Blackfin/BlackfinRegisterInfo.cpp @@ -221,7 +221,7 @@ static unsigned findScratchRegister(MachineBasicBlock::iterator II, unsigned BlackfinRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, - int SPAdj, int *Value, + int SPAdj, FrameIndexValue *Value, RegScavenger *RS) const { MachineInstr &MI = *II; MachineBasicBlock &MBB = *MI.getParent(); diff --git a/lib/Target/Blackfin/BlackfinRegisterInfo.h b/lib/Target/Blackfin/BlackfinRegisterInfo.h index 68ef08a..7cfb120 100644 --- a/lib/Target/Blackfin/BlackfinRegisterInfo.h +++ b/lib/Target/Blackfin/BlackfinRegisterInfo.h @@ -65,7 +65,7 @@ namespace llvm { MachineBasicBlock::iterator I) const; unsigned eliminateFrameIndex(MachineBasicBlock::iterator II, - int SPAdj, int *Value = NULL, + int SPAdj, FrameIndexValue *Value = NULL, RegScavenger *RS = NULL) const; void processFunctionBeforeCalleeSavedScan(MachineFunction &MF, diff --git a/lib/Target/CellSPU/CellSDKIntrinsics.td b/lib/Target/CellSPU/CellSDKIntrinsics.td index 5d759a4..1fe7aff 100644 --- a/lib/Target/CellSPU/CellSDKIntrinsics.td +++ b/lib/Target/CellSPU/CellSDKIntrinsics.td @@ -205,6 +205,7 @@ def CellSDKnand: // Shift/rotate intrinsics: //===----------------------------------------------------------------------===// +/* FIXME: These have (currently unenforced) type conflicts. */ def CellSDKshli: Pat<(int_spu_si_shli (v4i32 VECREG:$rA), uimm7:$val), (SHLIv4i32 VECREG:$rA, uimm7:$val)>; diff --git a/lib/Target/CellSPU/SPUInstrInfo.td b/lib/Target/CellSPU/SPUInstrInfo.td index f24ffd2..b96b64e 100644 --- a/lib/Target/CellSPU/SPUInstrInfo.td +++ b/lib/Target/CellSPU/SPUInstrInfo.td @@ -2370,7 +2370,7 @@ class ROTHInst<dag OOL, dag IOL, list<dag> pattern>: class ROTHVecInst<ValueType vectype>: ROTHInst<(outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB), [(set (vectype VECREG:$rT), - (SPUvec_rotl VECREG:$rA, VECREG:$rB))]>; + (SPUvec_rotl VECREG:$rA, (v8i16 VECREG:$rB)))]>; class ROTHRegInst<RegisterClass rclass>: ROTHInst<(outs rclass:$rT), (ins rclass:$rA, rclass:$rB), diff --git a/lib/Target/CellSPU/SPUMathInstr.td b/lib/Target/CellSPU/SPUMathInstr.td index 80ebde3..ed7129e 100644 --- a/lib/Target/CellSPU/SPUMathInstr.td +++ b/lib/Target/CellSPU/SPUMathInstr.td @@ -45,9 +45,9 @@ def : Pat<(mul (v8i16 VECREG:$rA), (v8i16 VECREG:$rB)), def MPYv4i32: Pat<(mul (v4i32 VECREG:$rA), (v4i32 VECREG:$rB)), (Av4i32 - (Av4i32 (MPYHv4i32 VECREG:$rA, VECREG:$rB), - (MPYHv4i32 VECREG:$rB, VECREG:$rA)), - (MPYUv4i32 VECREG:$rA, VECREG:$rB))>; + (v4i32 (Av4i32 (v4i32 (MPYHv4i32 VECREG:$rA, VECREG:$rB)), + (v4i32 (MPYHv4i32 VECREG:$rB, VECREG:$rA)))), + (v4i32 (MPYUv4i32 VECREG:$rA, VECREG:$rB)))>; def MPYi32: Pat<(mul R32C:$rA, R32C:$rB), diff --git a/lib/Target/CellSPU/SPUNodes.td b/lib/Target/CellSPU/SPUNodes.td index c722e4b..8507861 100644 --- a/lib/Target/CellSPU/SPUNodes.td +++ b/lib/Target/CellSPU/SPUNodes.td @@ -26,7 +26,7 @@ def callseq_end : SDNode<"ISD::CALLSEQ_END", SDT_SPUCallSeq, // Operand constraints: //===----------------------------------------------------------------------===// -def SDT_SPUCall : SDTypeProfile<0, -1, [SDTCisInt<0>]>; +def SDT_SPUCall : SDTypeProfile<0, -1, [SDTCisPtrTy<0>]>; def SPUcall : SDNode<"SPUISD::CALL", SDT_SPUCall, [SDNPHasChain, SDNPOptInFlag, SDNPOutFlag]>; diff --git a/lib/Target/CellSPU/SPURegisterInfo.cpp b/lib/Target/CellSPU/SPURegisterInfo.cpp index af94e67..4ba0cb1 100644 --- a/lib/Target/CellSPU/SPURegisterInfo.cpp +++ b/lib/Target/CellSPU/SPURegisterInfo.cpp @@ -328,7 +328,8 @@ SPURegisterInfo::eliminateCallFramePseudoInstr(MachineFunction &MF, unsigned SPURegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj, - int *Value, RegScavenger *RS) const + FrameIndexValue *Value, + RegScavenger *RS) const { unsigned i = 0; MachineInstr &MI = *II; diff --git a/lib/Target/CellSPU/SPURegisterInfo.h b/lib/Target/CellSPU/SPURegisterInfo.h index 9691cb6..48feb5c 100644 --- a/lib/Target/CellSPU/SPURegisterInfo.h +++ b/lib/Target/CellSPU/SPURegisterInfo.h @@ -64,7 +64,7 @@ namespace llvm { MachineBasicBlock::iterator I) const; //! Convert frame indicies into machine operands unsigned eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj, - int *Value = NULL, + FrameIndexValue *Value = NULL, RegScavenger *RS = NULL) const; //! Determine the frame's layour void determineFrameLayout(MachineFunction &MF) const; diff --git a/lib/Target/MBlaze/MBlazeCallingConv.td b/lib/Target/MBlaze/MBlazeCallingConv.td index dfc87f5..ddd4998 100644 --- a/lib/Target/MBlaze/MBlazeCallingConv.td +++ b/lib/Target/MBlaze/MBlazeCallingConv.td @@ -17,21 +17,6 @@ class CCIfSubtarget<string F, CCAction A>: // MBlaze ABI Calling Convention //===----------------------------------------------------------------------===// -def CC_MBlaze : CallingConv<[ - // Promote i8/i16 arguments to i32. - CCIfType<[i8, i16], CCPromoteToType<i32>>, - - // Integer arguments are passed in integer registers. - CCIfType<[i32], CCAssignToReg<[R5, R6, R7, R8, R9, R10]>>, - - // Single fp arguments are passed in floating point registers - CCIfType<[f32], CCAssignToReg<[F5, F6, F7, F8, F9, F10]>>, - - // 32-bit values get stored in stack slots that are 4 bytes in - // size and 4-byte aligned. - CCIfType<[i32, f32], CCAssignToStack<4, 4>> -]>; - def RetCC_MBlaze : CallingConv<[ // i32 are returned in registers R3, R4 CCIfType<[i32], CCAssignToReg<[R3, R4]>>, diff --git a/lib/Target/MBlaze/MBlazeISelDAGToDAG.cpp b/lib/Target/MBlaze/MBlazeISelDAGToDAG.cpp index a0ebea0..7e59c4a 100644 --- a/lib/Target/MBlaze/MBlazeISelDAGToDAG.cpp +++ b/lib/Target/MBlaze/MBlazeISelDAGToDAG.cpp @@ -129,15 +129,15 @@ SelectAddrRegReg(SDNode *Op, SDValue N, SDValue &Base, SDValue &Index) { N.getOpcode() == ISD::TargetGlobalAddress) return false; // direct calls. - if (N.getOperand(0).getOpcode() == ISD::TargetJumpTable || - N.getOperand(1).getOpcode() == ISD::TargetJumpTable) - return false; // jump tables. - int32_t imm = 0; if (N.getOpcode() == ISD::ADD || N.getOpcode() == ISD::OR) { if (isIntS32Immediate(N.getOperand(1), imm)) return false; // r+i + if (N.getOperand(0).getOpcode() == ISD::TargetJumpTable || + N.getOperand(1).getOpcode() == ISD::TargetJumpTable) + return false; // jump tables. + Base = N.getOperand(1); Index = N.getOperand(0); return true; diff --git a/lib/Target/MBlaze/MBlazeISelLowering.cpp b/lib/Target/MBlaze/MBlazeISelLowering.cpp index 7790248..f0864d0 100644 --- a/lib/Target/MBlaze/MBlazeISelLowering.cpp +++ b/lib/Target/MBlaze/MBlazeISelLowering.cpp @@ -138,6 +138,13 @@ MBlazeTargetLowering::MBlazeTargetLowering(MBlazeTargetMachine &TM) setOperationAction(ISD::JumpTable, MVT::i32, Custom); setOperationAction(ISD::ConstantPool, MVT::i32, Custom); + // Variable Argument support + setOperationAction(ISD::VASTART, MVT::Other, Custom); + setOperationAction(ISD::VAEND, MVT::Other, Expand); + setOperationAction(ISD::VAARG, MVT::Other, Expand); + setOperationAction(ISD::VACOPY, MVT::Other, Expand); + + // Operations not directly supported by MBlaze. setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32, Expand); setOperationAction(ISD::BR_JT, MVT::Other, Expand); @@ -186,6 +193,7 @@ SDValue MBlazeTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) { case ISD::GlobalTLSAddress: return LowerGlobalTLSAddress(Op, DAG); case ISD::JumpTable: return LowerJumpTable(Op, DAG); case ISD::SELECT_CC: return LowerSELECT_CC(Op, DAG); + case ISD::VASTART: return LowerVASTART(Op, DAG); } return SDValue(); } @@ -440,7 +448,6 @@ LowerConstantPool(SDValue Op, SelectionDAG &DAG) { ConstantPoolSDNode *N = cast<ConstantPoolSDNode>(Op); Constant *C = N->getConstVal(); SDValue Zero = DAG.getConstant(0, PtrVT); - // FIXME there isn't actually debug info here DebugLoc dl = Op.getDebugLoc(); SDValue CP = DAG.getTargetConstantPool(C, MVT::i32, N->getAlignment(), @@ -448,12 +455,71 @@ LowerConstantPool(SDValue Op, SelectionDAG &DAG) { return DAG.getNode(MBlazeISD::Wrap, dl, MVT::i32, CP); } +SDValue MBlazeTargetLowering::LowerVASTART(SDValue Op, SelectionDAG &DAG) { + DebugLoc dl = Op.getDebugLoc(); + SDValue FI = DAG.getFrameIndex(VarArgsFrameIndex, getPointerTy()); + + // vastart just stores the address of the VarArgsFrameIndex slot into the + // memory location argument. + const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue(); + return DAG.getStore(Op.getOperand(0), dl, FI, Op.getOperand(1), SV, 0, + false, false, 0); +} + //===----------------------------------------------------------------------===// // Calling Convention Implementation //===----------------------------------------------------------------------===// #include "MBlazeGenCallingConv.inc" +static bool CC_MBlaze2(unsigned ValNo, EVT ValVT, + EVT LocVT, CCValAssign::LocInfo LocInfo, + ISD::ArgFlagsTy ArgFlags, CCState &State) { + static const unsigned RegsSize=6; + static const unsigned IntRegs[] = { + MBlaze::R5, MBlaze::R6, MBlaze::R7, + MBlaze::R8, MBlaze::R9, MBlaze::R10 + }; + + static const unsigned FltRegs[] = { + MBlaze::F5, MBlaze::F6, MBlaze::F7, + MBlaze::F8, MBlaze::F9, MBlaze::F10 + }; + + unsigned Reg=0; + + // Promote i8 and i16 + if (LocVT == MVT::i8 || LocVT == MVT::i16) { + LocVT = MVT::i32; + if (ArgFlags.isSExt()) + LocInfo = CCValAssign::SExt; + else if (ArgFlags.isZExt()) + LocInfo = CCValAssign::ZExt; + else + LocInfo = CCValAssign::AExt; + } + + if (ValVT == MVT::i32) { + Reg = State.AllocateReg(IntRegs, RegsSize); + LocVT = MVT::i32; + } else if (ValVT == MVT::f32) { + Reg = State.AllocateReg(FltRegs, RegsSize); + LocVT = MVT::f32; + } + + if (!Reg) { + unsigned SizeInBytes = ValVT.getSizeInBits() >> 3; + unsigned Offset = State.AllocateStack(SizeInBytes, SizeInBytes); + State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo)); + } else { + unsigned SizeInBytes = ValVT.getSizeInBits() >> 3; + State.AllocateStack(SizeInBytes, SizeInBytes); + State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo)); + } + + return false; // CC must always match +} + //===----------------------------------------------------------------------===// // Call Calling Convention Implementation //===----------------------------------------------------------------------===// @@ -468,6 +534,9 @@ LowerCall(SDValue Chain, SDValue Callee, CallingConv::ID CallConv, const SmallVectorImpl<ISD::InputArg> &Ins, DebugLoc dl, SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) { + // MBlaze does not yet support tail call optimization + isTailCall = false; + MachineFunction &MF = DAG.getMachineFunction(); MachineFrameInfo *MFI = MF.getFrameInfo(); @@ -475,7 +544,7 @@ LowerCall(SDValue Chain, SDValue Callee, CallingConv::ID CallConv, SmallVector<CCValAssign, 16> ArgLocs; CCState CCInfo(CallConv, isVarArg, getTargetMachine(), ArgLocs, *DAG.getContext()); - CCInfo.AnalyzeCallOperands(Outs, CC_MBlaze); + CCInfo.AnalyzeCallOperands(Outs, CC_MBlaze2); // Get a count of how many bytes are to be pushed on the stack. unsigned NumBytes = CCInfo.getNextStackOffset(); @@ -487,7 +556,7 @@ LowerCall(SDValue Chain, SDValue Callee, CallingConv::ID CallConv, // First/LastArgStackLoc contains the first/last // "at stack" argument location. int LastArgStackLoc = 0; - unsigned FirstStackArgLoc = 4; + unsigned FirstStackArgLoc = 0; // Walk the register/memloc assignments, inserting copies/loads. for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { @@ -508,9 +577,6 @@ LowerCall(SDValue Chain, SDValue Callee, CallingConv::ID CallConv, case CCValAssign::AExt: Arg = DAG.getNode(ISD::ANY_EXTEND, dl, RegVT, Arg); break; - case CCValAssign::BCvt: - Arg = DAG.getNode(ISD::BIT_CONVERT, dl, RegVT, Arg); - break; } // Arguments that can be passed on register must be kept at @@ -617,7 +683,7 @@ LowerCallResult(SDValue Chain, SDValue InFlag, CallingConv::ID CallConv, RVLocs[i].getValVT(), InFlag).getValue(1); InFlag = Chain.getValue(2); InVals.push_back(Chain.getValue(0)); - } + } return Chain; } @@ -629,7 +695,6 @@ LowerCallResult(SDValue Chain, SDValue InFlag, CallingConv::ID CallConv, /// LowerFormalArguments - transform physical registers into /// virtual registers and generate load operations for /// arguments places on the stack. -/// TODO: isVarArg SDValue MBlazeTargetLowering:: LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, const SmallVectorImpl<ISD::InputArg> &Ins, @@ -640,16 +705,23 @@ LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, MBlazeFunctionInfo *MBlazeFI = MF.getInfo<MBlazeFunctionInfo>(); unsigned StackReg = MF.getTarget().getRegisterInfo()->getFrameRegister(MF); + VarArgsFrameIndex = 0; + + // Used with vargs to acumulate store chains. + std::vector<SDValue> OutChains; + + // Keep track of the last register used for arguments + unsigned ArgRegEnd = 0; // Assign locations to all of the incoming arguments. SmallVector<CCValAssign, 16> ArgLocs; CCState CCInfo(CallConv, isVarArg, getTargetMachine(), ArgLocs, *DAG.getContext()); - CCInfo.AnalyzeFormalArguments(Ins, CC_MBlaze); + CCInfo.AnalyzeFormalArguments(Ins, CC_MBlaze2); SDValue StackPtr; - unsigned FirstStackArgLoc = 4; + unsigned FirstStackArgLoc = 0; for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { CCValAssign &VA = ArgLocs[i]; @@ -657,6 +729,7 @@ LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, // Arguments stored on registers if (VA.isRegLoc()) { EVT RegVT = VA.getLocVT(); + ArgRegEnd = VA.getLocReg(); TargetRegisterClass *RC = 0; if (RegVT == MVT::i32) @@ -668,12 +741,13 @@ LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, // Transform the arguments stored on // physical registers into virtual ones - unsigned Reg = MF.addLiveIn(VA.getLocReg(), RC); + unsigned Reg = MF.addLiveIn(ArgRegEnd, RC); SDValue ArgValue = DAG.getCopyFromReg(Chain, dl, Reg, RegVT); // If this is an 8 or 16-bit value, it has been passed promoted // to 32 bits. Insert an assert[sz]ext to capture this, then - // truncate to the right size. + // truncate to the right size. If if is a floating point value + // then convert to the correct type. if (VA.getLocInfo() != CCValAssign::Full) { unsigned Opcode = 0; if (VA.getLocInfo() == CCValAssign::SExt) @@ -688,35 +762,14 @@ LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, InVals.push_back(ArgValue); - // To meet ABI, when VARARGS are passed on registers, the registers - // must have their values written to the caller stack frame. - if (isVarArg) { - if (StackPtr.getNode() == 0) - StackPtr = DAG.getRegister(StackReg, getPointerTy()); - - // The stack pointer offset is relative to the caller stack frame. - // Since the real stack size is unknown here, a negative SPOffset - // is used so there's a way to adjust these offsets when the stack - // size get known (on EliminateFrameIndex). A dummy SPOffset is - // used instead of a direct negative address (which is recorded to - // be used on emitPrologue) to avoid mis-calc of the first stack - // offset on PEI::calculateFrameObjectOffsets. - // Arguments are always 32-bit. - int FI = MFI->CreateFixedObject(4, 0, true, false); - MBlazeFI->recordStoreVarArgsFI(FI, -(FirstStackArgLoc+(i*4))); - SDValue PtrOff = DAG.getFrameIndex(FI, getPointerTy()); - - // emit ISD::STORE whichs stores the - // parameter value to a stack Location - InVals.push_back(DAG.getStore(Chain, dl, ArgValue, PtrOff, NULL, 0, - false, false, 0)); - } - } else { // VA.isRegLoc() // sanity check assert(VA.isMemLoc()); + // The last argument is not a register + ArgRegEnd = 0; + // The stack pointer offset is relative to the caller stack frame. // Since the real stack size is unknown here, a negative SPOffset // is used so there's a way to adjust these offsets when the stack @@ -737,6 +790,47 @@ LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, } } + // To meet ABI, when VARARGS are passed on registers, the registers + // must have their values written to the caller stack frame. If the last + // argument was placed in the stack, there's no need to save any register. + if ((isVarArg) && ArgRegEnd) { + if (StackPtr.getNode() == 0) + StackPtr = DAG.getRegister(StackReg, getPointerTy()); + + // The last register argument that must be saved is MBlaze::R10 + TargetRegisterClass *RC = MBlaze::CPURegsRegisterClass; + + unsigned Begin = MBlazeRegisterInfo::getRegisterNumbering(MBlaze::R5); + unsigned Start = MBlazeRegisterInfo::getRegisterNumbering(ArgRegEnd+1); + unsigned End = MBlazeRegisterInfo::getRegisterNumbering(MBlaze::R10); + unsigned StackLoc = ArgLocs.size()-1 + (Start - Begin); + + for (; Start <= End; ++Start, ++StackLoc) { + unsigned Reg = MBlazeRegisterInfo::getRegisterFromNumbering(Start); + unsigned LiveReg = MF.addLiveIn(Reg, RC); + SDValue ArgValue = DAG.getCopyFromReg(Chain, dl, LiveReg, MVT::i32); + + int FI = MFI->CreateFixedObject(4, 0, true, false); + MBlazeFI->recordStoreVarArgsFI(FI, -(4+(StackLoc*4))); + SDValue PtrOff = DAG.getFrameIndex(FI, getPointerTy()); + OutChains.push_back(DAG.getStore(Chain, dl, ArgValue, PtrOff, NULL, 0, + false, false, 0)); + + // Record the frame index of the first variable argument + // which is a value necessary to VASTART. + if (!VarArgsFrameIndex) + VarArgsFrameIndex = FI; + } + } + + // All stores are grouped in one node to allow the matching between + // the size of Ins and InVals. This only happens when on varg functions + if (!OutChains.empty()) { + OutChains.push_back(Chain); + Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, + &OutChains[0], OutChains.size()); + } + return Chain; } diff --git a/lib/Target/MBlaze/MBlazeISelLowering.h b/lib/Target/MBlaze/MBlazeISelLowering.h index 75d2552..f8b1470 100644 --- a/lib/Target/MBlaze/MBlazeISelLowering.h +++ b/lib/Target/MBlaze/MBlazeISelLowering.h @@ -63,6 +63,8 @@ namespace llvm { //===--------------------------------------------------------------------===// class MBlazeTargetLowering : public TargetLowering { + int VarArgsFrameIndex; // FrameIndex for start of varargs area. + public: explicit MBlazeTargetLowering(MBlazeTargetMachine &TM); @@ -96,6 +98,7 @@ namespace llvm { SDValue LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG); SDValue LowerJumpTable(SDValue Op, SelectionDAG &DAG); SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG); + SDValue LowerVASTART(SDValue Op, SelectionDAG &DAG); virtual SDValue LowerFormalArguments(SDValue Chain, diff --git a/lib/Target/MBlaze/MBlazeRegisterInfo.cpp b/lib/Target/MBlaze/MBlazeRegisterInfo.cpp index 9067f8b..6d528a2 100644 --- a/lib/Target/MBlaze/MBlazeRegisterInfo.cpp +++ b/lib/Target/MBlaze/MBlazeRegisterInfo.cpp @@ -85,6 +85,47 @@ unsigned MBlazeRegisterInfo::getRegisterNumbering(unsigned RegEnum) { return 0; // Not reached } +/// getRegisterFromNumbering - Given the enum value for some register, e.g. +/// MBlaze::R0, return the number that it corresponds to (e.g. 0). +unsigned MBlazeRegisterInfo::getRegisterFromNumbering(unsigned Reg) { + switch (Reg) { + case 0 : return MBlaze::R0; + case 1 : return MBlaze::R1; + case 2 : return MBlaze::R2; + case 3 : return MBlaze::R3; + case 4 : return MBlaze::R4; + case 5 : return MBlaze::R5; + case 6 : return MBlaze::R6; + case 7 : return MBlaze::R7; + case 8 : return MBlaze::R8; + case 9 : return MBlaze::R9; + case 10 : return MBlaze::R10; + case 11 : return MBlaze::R11; + case 12 : return MBlaze::R12; + case 13 : return MBlaze::R13; + case 14 : return MBlaze::R14; + case 15 : return MBlaze::R15; + case 16 : return MBlaze::R16; + case 17 : return MBlaze::R17; + case 18 : return MBlaze::R18; + case 19 : return MBlaze::R19; + case 20 : return MBlaze::R20; + case 21 : return MBlaze::R21; + case 22 : return MBlaze::R22; + case 23 : return MBlaze::R23; + case 24 : return MBlaze::R24; + case 25 : return MBlaze::R25; + case 26 : return MBlaze::R26; + case 27 : return MBlaze::R27; + case 28 : return MBlaze::R28; + case 29 : return MBlaze::R29; + case 30 : return MBlaze::R30; + case 31 : return MBlaze::R31; + default: llvm_unreachable("Unknown register number!"); + } + return 0; // Not reached +} + unsigned MBlazeRegisterInfo::getPICCallReg() { return MBlaze::R20; } @@ -180,9 +221,9 @@ void MBlazeRegisterInfo::adjustMBlazeStackFrame(MachineFunction &MF) const { } if (MFI->hasCalls()) { + MBlazeFI->setRAStackOffset(0); MFI->setObjectOffset(MFI->CreateStackObject(RegSize, RegSize, true), StackOffset); - MBlazeFI->setRAStackOffset(StackOffset); TopCPUSavedRegOff = StackOffset; StackOffset += RegSize; } @@ -219,7 +260,7 @@ eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, // direct reference. unsigned MBlazeRegisterInfo:: eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj, - int *Value, RegScavenger *RS) const { + FrameIndexValue *Value, RegScavenger *RS) const { MachineInstr &MI = *II; MachineFunction &MF = *MI.getParent()->getParent(); @@ -245,7 +286,7 @@ eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj, // as explained on LowerFormalArguments, detect negative offsets // and adjust SPOffsets considering the final stack size. - int Offset = ((spOffset < 0) ? (stackSize + (-(spOffset+4))) : (spOffset)); + int Offset = (spOffset < 0) ? (stackSize - spOffset) : (spOffset + 4); Offset += MI.getOperand(oi).getImm(); DEBUG(errs() << "Offset : " << Offset << "\n" << "<--------->\n"); @@ -272,6 +313,7 @@ emitPrologue(MachineFunction &MF) const { // No need to allocate space on the stack. if (StackSize == 0 && !MFI->hasCalls()) return; + if (StackSize < 28 && MFI->hasCalls()) StackSize = 28; int FPOffset = MBlazeFI->getFPStackOffset(); int RAOffset = MBlazeFI->getRAStackOffset(); @@ -307,9 +349,6 @@ emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const { MBlazeFunctionInfo *MBlazeFI = MF.getInfo<MBlazeFunctionInfo>(); DebugLoc dl = MBBI->getDebugLoc(); - // Get the number of bytes from FrameInfo - int NumBytes = (int) MFI->getStackSize(); - // Get the FI's where RA and FP are saved. int FPOffset = MBlazeFI->getFPStackOffset(); int RAOffset = MBlazeFI->getRAStackOffset(); @@ -333,11 +372,15 @@ emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const { .addImm(RAOffset).addReg(MBlaze::R1); } + // Get the number of bytes from FrameInfo + int StackSize = (int) MFI->getStackSize(); + if (StackSize < 28 && MFI->hasCalls()) StackSize = 28; + // adjust stack. // addi R1, R1, imm - if (NumBytes) { + if (StackSize) { BuildMI(MBB, MBBI, dl, TII.get(MBlaze::ADDI), MBlaze::R1) - .addReg(MBlaze::R1).addImm(NumBytes); + .addReg(MBlaze::R1).addImm(StackSize); } } diff --git a/lib/Target/MBlaze/MBlazeRegisterInfo.h b/lib/Target/MBlaze/MBlazeRegisterInfo.h index 4847f1e..b618bf4 100644 --- a/lib/Target/MBlaze/MBlazeRegisterInfo.h +++ b/lib/Target/MBlaze/MBlazeRegisterInfo.h @@ -43,6 +43,7 @@ struct MBlazeRegisterInfo : public MBlazeGenRegisterInfo { /// getRegisterNumbering - Given the enum value for some register, e.g. /// MBlaze::RA, return the number that it corresponds to (e.g. 31). static unsigned getRegisterNumbering(unsigned RegEnum); + static unsigned getRegisterFromNumbering(unsigned RegEnum); /// Get PIC indirect call register static unsigned getPICCallReg(); @@ -66,7 +67,7 @@ struct MBlazeRegisterInfo : public MBlazeGenRegisterInfo { /// Stack Frame Processing Methods unsigned eliminateFrameIndex(MachineBasicBlock::iterator II, - int SPAdj, int *Value = NULL, + int SPAdj, FrameIndexValue *Value = NULL, RegScavenger *RS = NULL) const; void processFunctionBeforeFrameFinalized(MachineFunction &MF) const; @@ -82,6 +83,11 @@ struct MBlazeRegisterInfo : public MBlazeGenRegisterInfo { unsigned getEHExceptionRegister() const; unsigned getEHHandlerRegister() const; + /// targetHandlesStackFrameRounding - Returns true if the target is + /// responsible for rounding up the stack frame (probably at emitPrologue + /// time). + bool targetHandlesStackFrameRounding() const { return true; } + int getDwarfRegNum(unsigned RegNum, bool isEH) const; }; diff --git a/lib/Target/MSP430/AsmPrinter/MSP430AsmPrinter.cpp b/lib/Target/MSP430/AsmPrinter/MSP430AsmPrinter.cpp index def5fc6..7a35eb0 100644 --- a/lib/Target/MSP430/AsmPrinter/MSP430AsmPrinter.cpp +++ b/lib/Target/MSP430/AsmPrinter/MSP430AsmPrinter.cpp @@ -98,12 +98,19 @@ void MSP430AsmPrinter::printOperand(const MachineInstr *MI, int OpNum, bool isMemOp = Modifier && !strcmp(Modifier, "mem"); uint64_t Offset = MO.getOffset(); - O << (isMemOp ? '&' : '#'); + // If the global address expression is a part of displacement field with a + // register base, we should not emit any prefix symbol here, e.g. + // mov.w &foo, r1 + // vs + // mov.w glb(r1), r2 + // Otherwise (!) msp430-as will silently miscompile the output :( + if (!Modifier || strcmp(Modifier, "nohash")) + O << (isMemOp ? '&' : '#'); if (Offset) O << '(' << Offset << '+'; O << *GetGlobalValueSymbol(MO.getGlobal()); - + if (Offset) O << ')'; @@ -124,15 +131,11 @@ void MSP430AsmPrinter::printSrcMemOperand(const MachineInstr *MI, int OpNum, const MachineOperand &Disp = MI->getOperand(OpNum+1); // Print displacement first - if (!Disp.isImm()) { - printOperand(MI, OpNum+1, "mem"); - } else { - if (!Base.getReg()) - O << '&'; - - printOperand(MI, OpNum+1, "nohash"); - } + // Imm here is in fact global address - print extra modifier. + if (Disp.isImm() && !Base.getReg()) + O << '&'; + printOperand(MI, OpNum+1, "nohash"); // Print register base field if (Base.getReg()) { diff --git a/lib/Target/MSP430/AsmPrinter/MSP430InstPrinter.cpp b/lib/Target/MSP430/AsmPrinter/MSP430InstPrinter.cpp index f6565bd..d7636e6 100644 --- a/lib/Target/MSP430/AsmPrinter/MSP430InstPrinter.cpp +++ b/lib/Target/MSP430/AsmPrinter/MSP430InstPrinter.cpp @@ -62,21 +62,26 @@ void MSP430InstPrinter::printSrcMemOperand(const MCInst *MI, unsigned OpNo, const MCOperand &Disp = MI->getOperand(OpNo+1); // Print displacement first - if (Disp.isExpr()) { - O << '&' << *Disp.getExpr(); - } else { - assert(Disp.isImm() && "Expected immediate in displacement field"); - if (!Base.getReg()) - O << '&'; + // If the global address expression is a part of displacement field with a + // register base, we should not emit any prefix symbol here, e.g. + // mov.w &foo, r1 + // vs + // mov.w glb(r1), r2 + // Otherwise (!) msp430-as will silently miscompile the output :( + if (!Base.getReg()) + O << '&'; + + if (Disp.isExpr()) + O << *Disp.getExpr(); + else { + assert(Disp.isImm() && "Expected immediate in displacement field"); O << Disp.getImm(); } - // Print register base field - if (Base.getReg()) { + if (Base.getReg()) O << '(' << getRegisterName(Base.getReg()) << ')'; - } } void MSP430InstPrinter::printCCOperand(const MCInst *MI, unsigned OpNo) { diff --git a/lib/Target/MSP430/AsmPrinter/MSP430MCInstLower.cpp b/lib/Target/MSP430/AsmPrinter/MSP430MCInstLower.cpp index 4eb7f3d..2e5ef8e 100644 --- a/lib/Target/MSP430/AsmPrinter/MSP430MCInstLower.cpp +++ b/lib/Target/MSP430/AsmPrinter/MSP430MCInstLower.cpp @@ -58,7 +58,7 @@ GetJumpTableSymbol(const MachineOperand &MO) const { } // Create a symbol for the name. - return Ctx.GetOrCreateSymbol(Name.str()); + return Ctx.GetOrCreateTemporarySymbol(Name.str()); } MCSymbol *MSP430MCInstLower:: @@ -74,7 +74,7 @@ GetConstantPoolIndexSymbol(const MachineOperand &MO) const { } // Create a symbol for the name. - return Ctx.GetOrCreateSymbol(Name.str()); + return Ctx.GetOrCreateTemporarySymbol(Name.str()); } MCOperand MSP430MCInstLower:: diff --git a/lib/Target/MSP430/MSP430RegisterInfo.cpp b/lib/Target/MSP430/MSP430RegisterInfo.cpp index 566d902..daac683 100644 --- a/lib/Target/MSP430/MSP430RegisterInfo.cpp +++ b/lib/Target/MSP430/MSP430RegisterInfo.cpp @@ -207,7 +207,7 @@ eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, unsigned MSP430RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, - int SPAdj, int *Value, + int SPAdj, FrameIndexValue *Value, RegScavenger *RS) const { assert(SPAdj == 0 && "Unexpected"); diff --git a/lib/Target/MSP430/MSP430RegisterInfo.h b/lib/Target/MSP430/MSP430RegisterInfo.h index aa08787..c8684df 100644 --- a/lib/Target/MSP430/MSP430RegisterInfo.h +++ b/lib/Target/MSP430/MSP430RegisterInfo.h @@ -50,7 +50,7 @@ public: MachineBasicBlock::iterator I) const; unsigned eliminateFrameIndex(MachineBasicBlock::iterator II, - int SPAdj, int *Value = NULL, + int SPAdj, FrameIndexValue *Value = NULL, RegScavenger *RS = NULL) const; void emitPrologue(MachineFunction &MF) const; diff --git a/lib/Target/Mips/MipsRegisterInfo.cpp b/lib/Target/Mips/MipsRegisterInfo.cpp index f923bed..f3c87bc 100644 --- a/lib/Target/Mips/MipsRegisterInfo.cpp +++ b/lib/Target/Mips/MipsRegisterInfo.cpp @@ -355,7 +355,7 @@ eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, // direct reference. unsigned MipsRegisterInfo:: eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj, - int *Value, RegScavenger *RS) const + FrameIndexValue *Value, RegScavenger *RS) const { MachineInstr &MI = *II; MachineFunction &MF = *MI.getParent()->getParent(); diff --git a/lib/Target/Mips/MipsRegisterInfo.h b/lib/Target/Mips/MipsRegisterInfo.h index 6a3ec00..9fd044c 100644 --- a/lib/Target/Mips/MipsRegisterInfo.h +++ b/lib/Target/Mips/MipsRegisterInfo.h @@ -64,7 +64,7 @@ struct MipsRegisterInfo : public MipsGenRegisterInfo { /// Stack Frame Processing Methods unsigned eliminateFrameIndex(MachineBasicBlock::iterator II, - int SPAdj, int *Value = NULL, + int SPAdj, FrameIndexValue *Value = NULL, RegScavenger *RS = NULL) const; void processFunctionBeforeFrameFinalized(MachineFunction &MF) const; diff --git a/lib/Target/PIC16/PIC16DebugInfo.cpp b/lib/Target/PIC16/PIC16DebugInfo.cpp index 877e4ff..da4e027 100644 --- a/lib/Target/PIC16/PIC16DebugInfo.cpp +++ b/lib/Target/PIC16/PIC16DebugInfo.cpp @@ -333,7 +333,7 @@ void PIC16DbgInfo::EmitCompositeTypeDecls(Module &M) { for (DebugInfoFinder::iterator I = DbgFinder.type_begin(), E = DbgFinder.type_end(); I != E; ++I) { DICompositeType CTy(*I); - if (CTy.isNull()) + if (!CTy.Verify()) continue; if (CTy.getTag() == dwarf::DW_TAG_union_type || CTy.getTag() == dwarf::DW_TAG_structure_type ) { diff --git a/lib/Target/PIC16/PIC16RegisterInfo.cpp b/lib/Target/PIC16/PIC16RegisterInfo.cpp index 8ba9a1d..30a1d4a 100644 --- a/lib/Target/PIC16/PIC16RegisterInfo.cpp +++ b/lib/Target/PIC16/PIC16RegisterInfo.cpp @@ -53,7 +53,7 @@ bool PIC16RegisterInfo::hasFP(const MachineFunction &MF) const { unsigned PIC16RegisterInfo:: eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj, - int *Value, RegScavenger *RS) const + FrameIndexValue *Value, RegScavenger *RS) const { /* NOT YET IMPLEMENTED */ return 0; diff --git a/lib/Target/PIC16/PIC16RegisterInfo.h b/lib/Target/PIC16/PIC16RegisterInfo.h index 1d5dbbf..6a9a038 100644 --- a/lib/Target/PIC16/PIC16RegisterInfo.h +++ b/lib/Target/PIC16/PIC16RegisterInfo.h @@ -49,7 +49,7 @@ class PIC16RegisterInfo : public PIC16GenRegisterInfo { virtual bool hasFP(const MachineFunction &MF) const; virtual unsigned eliminateFrameIndex(MachineBasicBlock::iterator MI, - int SPAdj, int *Value = NULL, + int SPAdj, FrameIndexValue *Value = NULL, RegScavenger *RS=NULL) const; void eliminateCallFramePseudoInstr(MachineFunction &MF, diff --git a/lib/Target/PowerPC/AsmPrinter/PPCAsmPrinter.cpp b/lib/Target/PowerPC/AsmPrinter/PPCAsmPrinter.cpp index ac901d0..3c7dfaf 100644 --- a/lib/Target/PowerPC/AsmPrinter/PPCAsmPrinter.cpp +++ b/lib/Target/PowerPC/AsmPrinter/PPCAsmPrinter.cpp @@ -309,8 +309,8 @@ namespace { const MCSymbol *&TOCEntry = TOC[Sym]; if (TOCEntry == 0) TOCEntry = OutContext. - GetOrCreateSymbol(StringRef(MAI->getPrivateGlobalPrefix()) + "C" + - Twine(LabelID++)); + GetOrCreateTemporarySymbol(StringRef(MAI->getPrivateGlobalPrefix()) + + "C" + Twine(LabelID++)); O << *TOCEntry << "@toc"; } @@ -672,14 +672,14 @@ static const MCSymbol *GetLazyPtr(const MCSymbol *Sym, MCContext &Ctx) { // Remove $stub suffix, add $lazy_ptr. SmallString<128> TmpStr(Sym->getName().begin(), Sym->getName().end()-5); TmpStr += "$lazy_ptr"; - return Ctx.GetOrCreateSymbol(TmpStr.str()); + return Ctx.GetOrCreateTemporarySymbol(TmpStr.str()); } static const MCSymbol *GetAnonSym(const MCSymbol *Sym, MCContext &Ctx) { // Add $tmp suffix to $stub, yielding $stub$tmp. SmallString<128> TmpStr(Sym->getName().begin(), Sym->getName().end()); TmpStr += "$tmp"; - return Ctx.GetOrCreateSymbol(TmpStr.str()); + return Ctx.GetOrCreateTemporarySymbol(TmpStr.str()); } void PPCDarwinAsmPrinter:: diff --git a/lib/Target/PowerPC/PPCISelLowering.cpp b/lib/Target/PowerPC/PPCISelLowering.cpp index 3d81afa..aeaa7c6 100644 --- a/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/lib/Target/PowerPC/PPCISelLowering.cpp @@ -3258,6 +3258,16 @@ PPCTargetLowering::LowerCall_Darwin(SDValue Chain, SDValue Callee, false, false, 0); } + // On Darwin, R12 must contain the address of an indirect callee. This does + // not mean the MTCTR instruction must use R12; it's easier to model this as + // an extra parameter, so do that. + if (!isTailCall && + !dyn_cast<GlobalAddressSDNode>(Callee) && + !dyn_cast<ExternalSymbolSDNode>(Callee) && + !isBLACompatibleAddress(Callee, DAG)) + RegsToPass.push_back(std::make_pair((unsigned)(isPPC64 ? PPC::X12 : + PPC::R12), Callee)); + // Build a sequence of copy-to-reg nodes chained together with token chain // and flag operands which copy the outgoing args into the appropriate regs. SDValue InFlag; diff --git a/lib/Target/PowerPC/PPCInstrAltivec.td b/lib/Target/PowerPC/PPCInstrAltivec.td index 3f4d329..3ff8f27 100644 --- a/lib/Target/PowerPC/PPCInstrAltivec.td +++ b/lib/Target/PowerPC/PPCInstrAltivec.td @@ -35,33 +35,33 @@ def vpkuwum_unary_shuffle : PatFrag<(ops node:$lhs, node:$rhs), def vmrglb_shuffle : PatFrag<(ops node:$lhs, node:$rhs), - (vector_shuffle node:$lhs, node:$rhs), [{ + (vector_shuffle (v16i8 node:$lhs), node:$rhs), [{ return PPC::isVMRGLShuffleMask(cast<ShuffleVectorSDNode>(N), 1, false); }]>; def vmrglh_shuffle : PatFrag<(ops node:$lhs, node:$rhs), - (vector_shuffle node:$lhs, node:$rhs), [{ + (vector_shuffle (v16i8 node:$lhs), node:$rhs), [{ return PPC::isVMRGLShuffleMask(cast<ShuffleVectorSDNode>(N), 2, false); }]>; def vmrglw_shuffle : PatFrag<(ops node:$lhs, node:$rhs), - (vector_shuffle node:$lhs, node:$rhs), [{ + (vector_shuffle (v16i8 node:$lhs), node:$rhs), [{ return PPC::isVMRGLShuffleMask(cast<ShuffleVectorSDNode>(N), 4, false); }]>; def vmrghb_shuffle : PatFrag<(ops node:$lhs, node:$rhs), - (vector_shuffle node:$lhs, node:$rhs), [{ + (vector_shuffle (v16i8 node:$lhs), node:$rhs), [{ return PPC::isVMRGHShuffleMask(cast<ShuffleVectorSDNode>(N), 1, false); }]>; def vmrghh_shuffle : PatFrag<(ops node:$lhs, node:$rhs), - (vector_shuffle node:$lhs, node:$rhs), [{ + (vector_shuffle (v16i8 node:$lhs), node:$rhs), [{ return PPC::isVMRGHShuffleMask(cast<ShuffleVectorSDNode>(N), 2, false); }]>; def vmrghw_shuffle : PatFrag<(ops node:$lhs, node:$rhs), - (vector_shuffle node:$lhs, node:$rhs), [{ + (vector_shuffle (v16i8 node:$lhs), node:$rhs), [{ return PPC::isVMRGHShuffleMask(cast<ShuffleVectorSDNode>(N), 4, false); }]>; def vmrglb_unary_shuffle : PatFrag<(ops node:$lhs, node:$rhs), - (vector_shuffle node:$lhs, node:$rhs), [{ + (vector_shuffle (v16i8 node:$lhs), node:$rhs), [{ return PPC::isVMRGLShuffleMask(cast<ShuffleVectorSDNode>(N), 1, true); }]>; def vmrglh_unary_shuffle : PatFrag<(ops node:$lhs, node:$rhs), diff --git a/lib/Target/PowerPC/PPCRegisterInfo.cpp b/lib/Target/PowerPC/PPCRegisterInfo.cpp index 0b509ac..31bca16 100644 --- a/lib/Target/PowerPC/PPCRegisterInfo.cpp +++ b/lib/Target/PowerPC/PPCRegisterInfo.cpp @@ -713,7 +713,7 @@ void PPCRegisterInfo::lowerCRSpilling(MachineBasicBlock::iterator II, unsigned PPCRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, - int SPAdj, int *Value, + int SPAdj, FrameIndexValue *Value, RegScavenger *RS) const { assert(SPAdj == 0 && "Unexpected"); diff --git a/lib/Target/PowerPC/PPCRegisterInfo.h b/lib/Target/PowerPC/PPCRegisterInfo.h index 3aeed80..43cf535 100644 --- a/lib/Target/PowerPC/PPCRegisterInfo.h +++ b/lib/Target/PowerPC/PPCRegisterInfo.h @@ -67,7 +67,7 @@ public: void lowerCRSpilling(MachineBasicBlock::iterator II, unsigned FrameIndex, int SPAdj, RegScavenger *RS) const; unsigned eliminateFrameIndex(MachineBasicBlock::iterator II, - int SPAdj, int *Value = NULL, + int SPAdj, FrameIndexValue *Value = NULL, RegScavenger *RS = NULL) const; /// determineFrameLayout - Determine the size of the frame and maximum call diff --git a/lib/Target/Sparc/SparcRegisterInfo.cpp b/lib/Target/Sparc/SparcRegisterInfo.cpp index 6f6183e..740e3bc 100644 --- a/lib/Target/Sparc/SparcRegisterInfo.cpp +++ b/lib/Target/Sparc/SparcRegisterInfo.cpp @@ -78,7 +78,7 @@ eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, unsigned SparcRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, - int SPAdj, int *Value, + int SPAdj, FrameIndexValue *Value, RegScavenger *RS) const { assert(SPAdj == 0 && "Unexpected"); diff --git a/lib/Target/Sparc/SparcRegisterInfo.h b/lib/Target/Sparc/SparcRegisterInfo.h index 8889ea6..24d43e3 100644 --- a/lib/Target/Sparc/SparcRegisterInfo.h +++ b/lib/Target/Sparc/SparcRegisterInfo.h @@ -44,7 +44,7 @@ struct SparcRegisterInfo : public SparcGenRegisterInfo { MachineBasicBlock::iterator I) const; unsigned eliminateFrameIndex(MachineBasicBlock::iterator II, - int SPAdj, int *Value = NULL, + int SPAdj, FrameIndexValue *Value = NULL, RegScavenger *RS = NULL) const; void processFunctionBeforeFrameFinalized(MachineFunction &MF) const; diff --git a/lib/Target/SystemZ/SystemZInstrInfo.td b/lib/Target/SystemZ/SystemZInstrInfo.td index a44f6d9..a75b85d 100644 --- a/lib/Target/SystemZ/SystemZInstrInfo.td +++ b/lib/Target/SystemZ/SystemZInstrInfo.td @@ -1112,7 +1112,8 @@ def : Pat<(SystemZcall (i64 texternalsym:$dst)), (CALLi texternalsym:$dst)>; // Arbitrary immediate support. def : Pat<(i32 imm:$src), - (EXTRACT_SUBREG (MOV64ri32 (i64 imm:$src)), subreg_32bit)>; + (EXTRACT_SUBREG (MOV64ri32 (GetI64FromI32 (i32 imm:$src))), + subreg_32bit)>; // Implement in terms of LLIHF/OILF. def : Pat<(i64 imm:$imm), diff --git a/lib/Target/SystemZ/SystemZOperands.td b/lib/Target/SystemZ/SystemZOperands.td index 156cace..0de50fd 100644 --- a/lib/Target/SystemZ/SystemZOperands.td +++ b/lib/Target/SystemZ/SystemZOperands.td @@ -67,6 +67,10 @@ def HI32 : SDNodeXForm<imm, [{ return getI32Imm(N->getZExtValue() >> 32); }]>; +def GetI64FromI32 : SDNodeXForm<imm, [{ + return CurDAG->getTargetConstant(N->getSExtValue(), MVT::i64); +}]>; + def i32ll16 : PatLeaf<(i32 imm), [{ // i32ll16 predicate - true if the 32-bit immediate has only rightmost 16 // bits set. diff --git a/lib/Target/SystemZ/SystemZRegisterInfo.cpp b/lib/Target/SystemZ/SystemZRegisterInfo.cpp index fe50c90..ca2fe6f 100644 --- a/lib/Target/SystemZ/SystemZRegisterInfo.cpp +++ b/lib/Target/SystemZ/SystemZRegisterInfo.cpp @@ -110,7 +110,7 @@ int SystemZRegisterInfo::getFrameIndexOffset(const MachineFunction &MF, unsigned SystemZRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, - int SPAdj, int *Value, + int SPAdj, FrameIndexValue *Value, RegScavenger *RS) const { assert(SPAdj == 0 && "Unxpected"); diff --git a/lib/Target/SystemZ/SystemZRegisterInfo.h b/lib/Target/SystemZ/SystemZRegisterInfo.h index fabd4e8..99e396a 100644 --- a/lib/Target/SystemZ/SystemZRegisterInfo.h +++ b/lib/Target/SystemZ/SystemZRegisterInfo.h @@ -56,7 +56,7 @@ struct SystemZRegisterInfo : public SystemZGenRegisterInfo { MachineBasicBlock::iterator I) const; unsigned eliminateFrameIndex(MachineBasicBlock::iterator II, - int SPAdj, int *Value = NULL, + int SPAdj, FrameIndexValue *Value = NULL, RegScavenger *RS = NULL) const; diff --git a/lib/Target/TargetLoweringObjectFile.cpp b/lib/Target/TargetLoweringObjectFile.cpp index 82619c7..8c12039 100644 --- a/lib/Target/TargetLoweringObjectFile.cpp +++ b/lib/Target/TargetLoweringObjectFile.cpp @@ -56,6 +56,10 @@ TargetLoweringObjectFile::TargetLoweringObjectFile() : Ctx(0) { DwarfARangesSection = 0; DwarfRangesSection = 0; DwarfMacroInfoSection = 0; + + IsFunctionEHSymbolGlobal = false; + IsFunctionEHFrameSymbolPrivate = true; + SupportsWeakOmittedEHFrame = true; } TargetLoweringObjectFile::~TargetLoweringObjectFile() { @@ -295,7 +299,12 @@ getSymbolForDwarfGlobalReference(const GlobalValue *GV, Mangler *Mang, // FIXME: Use GetGlobalValueSymbol. SmallString<128> Name; Mang->getNameWithPrefix(Name, GV, false); - const MCSymbol *Sym = getContext().GetOrCreateSymbol(Name.str()); + const MCSymbol *Sym; + + if (GV->hasPrivateLinkage()) + Sym = getContext().GetOrCreateTemporarySymbol(Name.str()); + else + Sym = getContext().GetOrCreateSymbol(Name.str()); return getSymbolForDwarfReference(Sym, MMI, Encoding); } diff --git a/lib/Target/X86/AsmPrinter/X86AsmPrinter.cpp b/lib/Target/X86/AsmPrinter/X86AsmPrinter.cpp index 8cab24c..caf84b6 100644 --- a/lib/Target/X86/AsmPrinter/X86AsmPrinter.cpp +++ b/lib/Target/X86/AsmPrinter/X86AsmPrinter.cpp @@ -26,6 +26,7 @@ #include "llvm/Module.h" #include "llvm/Type.h" #include "llvm/Assembly/Writer.h" +#include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCSectionMachO.h" @@ -36,7 +37,6 @@ #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FormattedStream.h" -#include "llvm/MC/MCAsmInfo.h" #include "llvm/Target/Mangler.h" #include "llvm/Target/TargetOptions.h" #include "llvm/Target/TargetRegistry.h" @@ -56,7 +56,11 @@ void X86AsmPrinter::PrintPICBaseSymbol() const { MCSymbol *X86AsmPrinter::GetGlobalValueSymbol(const GlobalValue *GV) const { SmallString<60> NameStr; Mang->getNameWithPrefix(NameStr, GV, false); - MCSymbol *Symb = OutContext.GetOrCreateSymbol(NameStr.str()); + MCSymbol *Symb; + if (GV->hasPrivateLinkage()) + Symb = OutContext.GetOrCreateTemporarySymbol(NameStr.str()); + else + Symb = OutContext.GetOrCreateSymbol(NameStr.str()); if (Subtarget->isTargetCygMing()) { X86COFFMachineModuleInfo &COFFMMI = diff --git a/lib/Target/X86/AsmPrinter/X86MCInstLower.cpp b/lib/Target/X86/AsmPrinter/X86MCInstLower.cpp index fa8d13d..b8a6eeb 100644 --- a/lib/Target/X86/AsmPrinter/X86MCInstLower.cpp +++ b/lib/Target/X86/AsmPrinter/X86MCInstLower.cpp @@ -89,7 +89,7 @@ GetSymbolFromOperand(const MachineOperand &MO) const { case X86II::MO_DARWIN_NONLAZY: case X86II::MO_DARWIN_NONLAZY_PIC_BASE: { Name += "$non_lazy_ptr"; - MCSymbol *Sym = Ctx.GetOrCreateSymbol(Name.str()); + MCSymbol *Sym = Ctx.GetOrCreateTemporarySymbol(Name.str()); MCSymbol *&StubSym = getMachOMMI().getGVStubEntry(Sym); if (StubSym == 0) { @@ -100,7 +100,7 @@ GetSymbolFromOperand(const MachineOperand &MO) const { } case X86II::MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE: { Name += "$non_lazy_ptr"; - MCSymbol *Sym = Ctx.GetOrCreateSymbol(Name.str()); + MCSymbol *Sym = Ctx.GetOrCreateTemporarySymbol(Name.str()); MCSymbol *&StubSym = getMachOMMI().getHiddenGVStubEntry(Sym); if (StubSym == 0) { assert(MO.isGlobal() && "Extern symbol not handled yet"); @@ -110,7 +110,7 @@ GetSymbolFromOperand(const MachineOperand &MO) const { } case X86II::MO_DARWIN_STUB: { Name += "$stub"; - MCSymbol *Sym = Ctx.GetOrCreateSymbol(Name.str()); + MCSymbol *Sym = Ctx.GetOrCreateTemporarySymbol(Name.str()); MCSymbol *&StubSym = getMachOMMI().getFnStubEntry(Sym); if (StubSym) return Sym; @@ -119,7 +119,7 @@ GetSymbolFromOperand(const MachineOperand &MO) const { StubSym = AsmPrinter.GetGlobalValueSymbol(MO.getGlobal()); } else { Name.erase(Name.end()-5, Name.end()); - StubSym = Ctx.GetOrCreateSymbol(Name.str()); + StubSym = Ctx.GetOrCreateTemporarySymbol(Name.str()); } return Sym; } @@ -394,7 +394,8 @@ void X86AsmPrinter::EmitInstruction(const MachineInstr *MI) { // However, we can't generate a ".", so just emit a new label here and refer // to it. We know that this operand flag occurs at most once per function. const char *Prefix = MAI->getPrivateGlobalPrefix(); - MCSymbol *DotSym = OutContext.GetOrCreateSymbol(Twine(Prefix)+"picbaseref"+ + MCSymbol *DotSym = OutContext.GetOrCreateTemporarySymbol(Twine(Prefix)+ + "picbaseref" + Twine(getFunctionNumber())); OutStreamer.EmitLabel(DotSym); diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index 8384ab7..0cfcbb6 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -1105,8 +1105,8 @@ MCSymbol * X86TargetLowering::getPICBaseSymbol(const MachineFunction *MF, MCContext &Ctx) const { const MCAsmInfo &MAI = *getTargetMachine().getMCAsmInfo(); - return Ctx.GetOrCreateSymbol(Twine(MAI.getPrivateGlobalPrefix())+ - Twine(MF->getFunctionNumber())+"$pb"); + return Ctx.GetOrCreateTemporarySymbol(Twine(MAI.getPrivateGlobalPrefix())+ + Twine(MF->getFunctionNumber())+"$pb"); } @@ -6418,24 +6418,13 @@ X86TargetLowering::LowerDYNAMIC_STACKALLOC(SDValue Op, EVT IntPtr = getPointerTy(); EVT SPTy = Subtarget->is64Bit() ? MVT::i64 : MVT::i32; - Chain = DAG.getCALLSEQ_START(Chain, DAG.getIntPtrConstant(0, true)); - Chain = DAG.getCopyToReg(Chain, dl, X86::EAX, Size, Flag); Flag = Chain.getValue(1); - SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Flag); - SDValue Ops[] = { Chain, - DAG.getTargetExternalSymbol("_alloca", IntPtr), - DAG.getRegister(X86::EAX, IntPtr), - DAG.getRegister(X86StackPtr, SPTy), - Flag }; - Chain = DAG.getNode(X86ISD::CALL, dl, NodeTys, Ops, 5); - Flag = Chain.getValue(1); + SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Flag); - Chain = DAG.getCALLSEQ_END(Chain, - DAG.getIntPtrConstant(0, true), - DAG.getIntPtrConstant(0, true), - Flag); + Chain = DAG.getNode(X86ISD::MINGW_ALLOCA, dl, NodeTys, Chain, Flag); + Flag = Chain.getValue(1); Chain = DAG.getCopyFromReg(Chain, dl, X86StackPtr, SPTy).getValue(1); @@ -7741,6 +7730,7 @@ const char *X86TargetLowering::getTargetNodeName(unsigned Opcode) const { case X86ISD::MUL_IMM: return "X86ISD::MUL_IMM"; case X86ISD::PTEST: return "X86ISD::PTEST"; case X86ISD::VASTART_SAVE_XMM_REGS: return "X86ISD::VASTART_SAVE_XMM_REGS"; + case X86ISD::MINGW_ALLOCA: return "X86ISD::MINGW_ALLOCA"; } } @@ -8410,6 +8400,29 @@ X86TargetLowering::EmitLoweredSelect(MachineInstr *MI, return BB; } +MachineBasicBlock * +X86TargetLowering::EmitLoweredMingwAlloca(MachineInstr *MI, + MachineBasicBlock *BB, + DenseMap<MachineBasicBlock*, MachineBasicBlock*> *EM) const { + const TargetInstrInfo *TII = getTargetMachine().getInstrInfo(); + DebugLoc DL = MI->getDebugLoc(); + MachineFunction *F = BB->getParent(); + + // The lowering is pretty easy: we're just emitting the call to _alloca. The + // non-trivial part is impdef of ESP. + // FIXME: The code should be tweaked as soon as we'll try to do codegen for + // mingw-w64. + + BuildMI(BB, DL, TII->get(X86::CALLpcrel32)) + .addExternalSymbol("_alloca") + .addReg(X86::EAX, RegState::Implicit) + .addReg(X86::ESP, RegState::Implicit) + .addReg(X86::EAX, RegState::Define | RegState::Implicit) + .addReg(X86::ESP, RegState::Define | RegState::Implicit); + + F->DeleteMachineInstr(MI); // The pseudo instruction is gone now. + return BB; +} MachineBasicBlock * X86TargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI, @@ -8417,6 +8430,8 @@ X86TargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI, DenseMap<MachineBasicBlock*, MachineBasicBlock*> *EM) const { switch (MI->getOpcode()) { default: assert(false && "Unexpected instr type to insert"); + case X86::MINGW_ALLOCA: + return EmitLoweredMingwAlloca(MI, BB, EM); case X86::CMOV_GR8: case X86::CMOV_V1I64: case X86::CMOV_FR32: diff --git a/lib/Target/X86/X86ISelLowering.h b/lib/Target/X86/X86ISelLowering.h index ffaf1cf..4c12fcc 100644 --- a/lib/Target/X86/X86ISelLowering.h +++ b/lib/Target/X86/X86ISelLowering.h @@ -249,6 +249,9 @@ namespace llvm { // with control flow. VASTART_SAVE_XMM_REGS, + // MINGW_ALLOCA - MingW's __alloca call to do stack probing. + MINGW_ALLOCA, + // ATOMADD64_DAG, ATOMSUB64_DAG, ATOMOR64_DAG, ATOMAND64_DAG, // ATOMXOR64_DAG, ATOMNAND64_DAG, ATOMSWAP64_DAG - // Atomic 64-bit binary operations. @@ -259,6 +262,10 @@ namespace llvm { ATOMAND64_DAG, ATOMNAND64_DAG, ATOMSWAP64_DAG + + // WARNING: Do not add anything in the end unless you want the node to + // have memop! In fact, starting from ATOMADD64_DAG all opcodes will be + // thought as target memory ops! }; } @@ -789,7 +796,11 @@ namespace llvm { MachineBasicBlock *EmitLoweredSelect(MachineInstr *I, MachineBasicBlock *BB, DenseMap<MachineBasicBlock*, MachineBasicBlock*> *EM) const; - + + MachineBasicBlock *EmitLoweredMingwAlloca(MachineInstr *MI, + MachineBasicBlock *BB, + DenseMap<MachineBasicBlock*, MachineBasicBlock*> *EM) const; + /// Emit nodes that will be selected as "test Op0,Op0", or something /// equivalent, for use with the given x86 condition code. SDValue EmitTest(SDValue Op0, unsigned X86CC, SelectionDAG &DAG); diff --git a/lib/Target/X86/X86Instr64bit.td b/lib/Target/X86/X86Instr64bit.td index 8462255..8e684c9 100644 --- a/lib/Target/X86/X86Instr64bit.td +++ b/lib/Target/X86/X86Instr64bit.td @@ -2473,7 +2473,7 @@ let isTwoAddress = 1 in { defm PINSRQ : SS41I_insert64<0x22, "pinsrq">; // -disable-16bit support. -def : Pat<(truncstorei16 (i64 imm:$src), addr:$dst), +def : Pat<(truncstorei16 (i16 imm:$src), addr:$dst), (MOV16mi addr:$dst, imm:$src)>; def : Pat<(truncstorei16 GR64:$src, addr:$dst), (MOV16mr addr:$dst, (EXTRACT_SUBREG GR64:$src, x86_subreg_16bit))>; diff --git a/lib/Target/X86/X86InstrInfo.cpp b/lib/Target/X86/X86InstrInfo.cpp index 39bda04..4fd91bb 100644 --- a/lib/Target/X86/X86InstrInfo.cpp +++ b/lib/Target/X86/X86InstrInfo.cpp @@ -2525,6 +2525,11 @@ MachineInstr* X86InstrInfo::foldMemoryOperandImpl(MachineFunction &MF, // Folding a V_SET0 or V_SETALLONES as a load, to ease register pressure. // Create a constant-pool entry and operands to load from it. + // Medium and large mode can't fold loads this way. + if (TM.getCodeModel() != CodeModel::Small && + TM.getCodeModel() != CodeModel::Kernel) + return NULL; + // x86-32 PIC requires a PIC base register for constant pools. unsigned PICBase = 0; if (TM.getRelocationModel() == Reloc::PIC_) { diff --git a/lib/Target/X86/X86InstrInfo.td b/lib/Target/X86/X86InstrInfo.td index d46b946..071c5aa 100644 --- a/lib/Target/X86/X86InstrInfo.td +++ b/lib/Target/X86/X86InstrInfo.td @@ -65,7 +65,7 @@ def SDT_X86VASTART_SAVE_XMM_REGS : SDTypeProfile<0, -1, [SDTCisVT<0, i8>, def SDTX86RepStr : SDTypeProfile<0, 1, [SDTCisVT<0, OtherVT>]>; -def SDTX86RdTsc : SDTypeProfile<0, 0, []>; +def SDTX86Void : SDTypeProfile<0, 0, []>; def SDTX86Wrapper : SDTypeProfile<1, 1, [SDTCisSameAs<0, 1>, SDTCisPtrTy<0>]>; @@ -143,7 +143,7 @@ def X86rep_movs: SDNode<"X86ISD::REP_MOVS", SDTX86RepStr, [SDNPHasChain, SDNPInFlag, SDNPOutFlag, SDNPMayStore, SDNPMayLoad]>; -def X86rdtsc : SDNode<"X86ISD::RDTSC_DAG",SDTX86RdTsc, +def X86rdtsc : SDNode<"X86ISD::RDTSC_DAG", SDTX86Void, [SDNPHasChain, SDNPOutFlag, SDNPSideEffect]>; def X86Wrapper : SDNode<"X86ISD::Wrapper", SDTX86Wrapper>; @@ -178,6 +178,9 @@ def X86and_flag : SDNode<"X86ISD::AND", SDTBinaryArithWithFlags, def X86mul_imm : SDNode<"X86ISD::MUL_IMM", SDTIntBinOp>; +def X86MingwAlloca : SDNode<"X86ISD::MINGW_ALLOCA", SDTX86Void, + [SDNPHasChain, SDNPInFlag, SDNPOutFlag]>; + //===----------------------------------------------------------------------===// // X86 Operand Definitions. // @@ -519,7 +522,7 @@ def ADJCALLSTACKUP32 : I<0, Pseudo, (outs), (ins i32imm:$amt1, i32imm:$amt2), } // x86-64 va_start lowering magic. -let usesCustomInserter = 1 in +let usesCustomInserter = 1 in { def VASTART_SAVE_XMM_REGS : I<0, Pseudo, (outs), (ins GR8:$al, @@ -530,6 +533,19 @@ def VASTART_SAVE_XMM_REGS : I<0, Pseudo, imm:$regsavefi, imm:$offset)]>; +// Dynamic stack allocation yields _alloca call for Cygwin/Mingw targets. Calls +// to _alloca is needed to probe the stack when allocating more than 4k bytes in +// one go. Touching the stack at 4K increments is necessary to ensure that the +// guard pages used by the OS virtual memory manager are allocated in correct +// sequence. +// The main point of having separate instruction are extra unmodelled effects +// (compared to ordinary calls) like stack pointer change. + +def MINGW_ALLOCA : I<0, Pseudo, (outs), (ins), + "# dynamic stack allocation", + [(X86MingwAlloca)]>; +} + // Nop let neverHasSideEffects = 1 in { def NOOP : I<0x90, RawFrm, (outs), (ins), "nop", []>; @@ -2631,6 +2647,17 @@ def ADD32rr : I<0x01, MRMDestReg, (outs GR32:$dst), } // end isConvertibleToThreeAddress } // end isCommutable +// These are alternate spellings for use by the disassembler, we mark them as +// code gen only to ensure they aren't matched by the assembler. +let isCodeGenOnly = 1 in { + def ADD8rr_alt: I<0x02, MRMSrcReg, (outs GR8:$dst), (ins GR8:$src1, GR8:$src2), + "add{b}\t{$src2, $dst|$dst, $src2}", []>; + def ADD16rr_alt: I<0x03, MRMSrcReg,(outs GR16:$dst),(ins GR16:$src1, GR16:$src2), + "add{w}\t{$src2, $dst|$dst, $src2}", []>, OpSize; + def ADD32rr_alt: I<0x03, MRMSrcReg,(outs GR16:$dst),(ins GR16:$src1, GR16:$src2), + "add{l}\t{$src2, $dst|$dst, $src2}", []>; +} + // Register-Memory Addition def ADD8rm : I<0x02, MRMSrcMem, (outs GR8 :$dst), (ins GR8 :$src1, i8mem :$src2), @@ -2648,15 +2675,6 @@ def ADD32rm : I<0x03, MRMSrcMem, (outs GR32:$dst), [(set GR32:$dst, (add GR32:$src1, (load addr:$src2))), (implicit EFLAGS)]>; -// Register-Register Addition - Equivalent to the normal rr forms (ADD8rr, -// ADD16rr, and ADD32rr), but differently encoded. -def ADD8mrmrr: I<0x02, MRMSrcReg, (outs GR8:$dst), (ins GR8:$src1, GR8:$src2), - "add{b}\t{$src2, $dst|$dst, $src2}", []>; -def ADD16mrmrr: I<0x03, MRMSrcReg,(outs GR16:$dst),(ins GR16:$src1, GR16:$src2), - "add{w}\t{$src2, $dst|$dst, $src2}", []>, OpSize; -def ADD32mrmrr: I<0x03, MRMSrcReg,(outs GR16:$dst),(ins GR16:$src1, GR16:$src2), - "add{l}\t{$src2, $dst|$dst, $src2}", []>; - // Register-Integer Addition def ADD8ri : Ii8<0x80, MRM0r, (outs GR8:$dst), (ins GR8:$src1, i8imm:$src2), "add{b}\t{$src2, $dst|$dst, $src2}", @@ -3119,16 +3137,16 @@ def IMUL32rmi8 : Ii8<0x6B, MRMSrcMem, // GR32 = [mem32]*I8 // let Defs = [EFLAGS] in { let isCommutable = 1 in { // TEST X, Y --> TEST Y, X -def TEST8rr : I<0x84, MRMDestReg, (outs), (ins GR8:$src1, GR8:$src2), +def TEST8rr : I<0x84, MRMSrcReg, (outs), (ins GR8:$src1, GR8:$src2), "test{b}\t{$src2, $src1|$src1, $src2}", [(X86cmp (and_su GR8:$src1, GR8:$src2), 0), (implicit EFLAGS)]>; -def TEST16rr : I<0x85, MRMDestReg, (outs), (ins GR16:$src1, GR16:$src2), +def TEST16rr : I<0x85, MRMSrcReg, (outs), (ins GR16:$src1, GR16:$src2), "test{w}\t{$src2, $src1|$src1, $src2}", [(X86cmp (and_su GR16:$src1, GR16:$src2), 0), (implicit EFLAGS)]>, OpSize; -def TEST32rr : I<0x85, MRMDestReg, (outs), (ins GR32:$src1, GR32:$src2), +def TEST32rr : I<0x85, MRMSrcReg, (outs), (ins GR32:$src1, GR32:$src2), "test{l}\t{$src2, $src1|$src1, $src2}", [(X86cmp (and_su GR32:$src1, GR32:$src2), 0), (implicit EFLAGS)]>; @@ -3437,12 +3455,18 @@ def CMP32rm : I<0x3B, MRMSrcMem, "cmp{l}\t{$src2, $src1|$src1, $src2}", [(X86cmp GR32:$src1, (loadi32 addr:$src2)), (implicit EFLAGS)]>; -def CMP8mrmrr : I<0x3A, MRMSrcReg, (outs), (ins GR8:$src1, GR8:$src2), - "cmp{b}\t{$src2, $src1|$src1, $src2}", []>; -def CMP16mrmrr : I<0x3B, MRMSrcReg, (outs), (ins GR16:$src1, GR16:$src2), - "cmp{w}\t{$src2, $src1|$src1, $src2}", []>, OpSize; -def CMP32mrmrr : I<0x3B, MRMSrcReg, (outs), (ins GR32:$src1, GR32:$src2), - "cmp{l}\t{$src2, $src1|$src1, $src2}", []>; + +// These are alternate spellings for use by the disassembler, we mark them as +// code gen only to ensure they aren't matched by the assembler. +let isCodeGenOnly = 1 in { + def CMP8rr_alt : I<0x3A, MRMSrcReg, (outs), (ins GR8:$src1, GR8:$src2), + "cmp{b}\t{$src2, $src1|$src1, $src2}", []>; + def CMP16rr_alt : I<0x3B, MRMSrcReg, (outs), (ins GR16:$src1, GR16:$src2), + "cmp{w}\t{$src2, $src1|$src1, $src2}", []>, OpSize; + def CMP32rr_alt : I<0x3B, MRMSrcReg, (outs), (ins GR32:$src1, GR32:$src2), + "cmp{l}\t{$src2, $src1|$src1, $src2}", []>; +} + def CMP8ri : Ii8<0x80, MRM7r, (outs), (ins GR8:$src1, i8imm:$src2), "cmp{b}\t{$src2, $src1|$src1, $src2}", @@ -4236,7 +4260,7 @@ def VMWRITE32rr : I<0x79, MRMSrcReg, (outs GR32:$dst), (ins GR32:$src), // 0F 01 C4 def VMXOFF : I<0x01, MRM_C4, (outs), (ins), "vmxoff", []>, TB; def VMXON : I<0xC7, MRM6m, (outs), (ins i64mem:$vmxon), - "vmxon\t{$vmxon}", []>, XD; + "vmxon\t{$vmxon}", []>, XS; //===----------------------------------------------------------------------===// // Non-Instruction Patterns @@ -5134,7 +5158,7 @@ def : Pat<(parallel (store (X86and_flag (loadi32 addr:$dst), i32immSExt8:$src2), (AND32mi8 addr:$dst, i32immSExt8:$src2)>; // -disable-16bit support. -def : Pat<(truncstorei16 (i32 imm:$src), addr:$dst), +def : Pat<(truncstorei16 (i16 imm:$src), addr:$dst), (MOV16mi addr:$dst, imm:$src)>; def : Pat<(truncstorei16 GR32:$src, addr:$dst), (MOV16mr addr:$dst, (EXTRACT_SUBREG GR32:$src, x86_subreg_16bit))>; diff --git a/lib/Target/X86/X86InstrMMX.td b/lib/Target/X86/X86InstrMMX.td index c8e0723..eea0eb8 100644 --- a/lib/Target/X86/X86InstrMMX.td +++ b/lib/Target/X86/X86InstrMMX.td @@ -160,7 +160,8 @@ def MMX_MOVQ2DQrr : SSDIi8<0xD6, MRMSrcReg, (outs VR128:$dst), (ins VR64:$src), "movq2dq\t{$src, $dst|$dst, $src}", [(set VR128:$dst, (movl immAllZerosV, - (v2i64 (scalar_to_vector (i64 (bitconvert VR64:$src))))))]>; + (v2i64 (scalar_to_vector + (i64 (bitconvert (v1i64 VR64:$src)))))))]>; let neverHasSideEffects = 1 in def MMX_MOVQ2FR64rr: SSDIi8<0xD6, MRMSrcReg, (outs FR64:$dst), (ins VR64:$src), @@ -271,9 +272,9 @@ defm MMX_PSRAD : MMXI_binop_rmi_int<0xE2, 0x72, MRM4r, "psrad", // Shift up / down and insert zero's. def : Pat<(v1i64 (X86vshl VR64:$src, (i8 imm:$amt))), - (v1i64 (MMX_PSLLQri VR64:$src, imm:$amt))>; + (MMX_PSLLQri VR64:$src, imm:$amt)>; def : Pat<(v1i64 (X86vshr VR64:$src, (i8 imm:$amt))), - (v1i64 (MMX_PSRLQri VR64:$src, imm:$amt))>; + (MMX_PSRLQri VR64:$src, imm:$amt)>; // Comparison Instructions defm MMX_PCMPEQB : MMXI_binop_rm_int<0x74, "pcmpeqb", int_x86_mmx_pcmpeq_b>; @@ -577,7 +578,7 @@ let AddedComplexity = 20 in { // Clear top half. let AddedComplexity = 15 in { def : Pat<(v2i32 (X86vzmovl VR64:$src)), - (MMX_PUNPCKLDQrr VR64:$src, (MMX_V_SET0))>; + (MMX_PUNPCKLDQrr VR64:$src, (v2i32 (MMX_V_SET0)))>; } // Patterns to perform canonical versions of vector shuffling. diff --git a/lib/Target/X86/X86InstrSSE.td b/lib/Target/X86/X86InstrSSE.td index 2743dba..bd6e1b8 100644 --- a/lib/Target/X86/X86InstrSSE.td +++ b/lib/Target/X86/X86InstrSSE.td @@ -385,7 +385,7 @@ def MOVSSrr : SSI<0x10, MRMSrcReg, // Extract the low 32-bit value from one vector and insert it into another. let AddedComplexity = 15 in def : Pat<(v4f32 (movl VR128:$src1, VR128:$src2)), - (MOVSSrr VR128:$src1, + (MOVSSrr (v4f32 VR128:$src1), (EXTRACT_SUBREG (v4f32 VR128:$src2), x86_subreg_ss))>; // Implicitly promote a 32-bit scalar to a vector. @@ -827,7 +827,7 @@ let Constraints = "$src1 = $dst" in { def : Pat<(movlhps VR128:$src1, (bc_v4i32 (v2i64 (X86vzload addr:$src2)))), - (MOVHPSrm VR128:$src1, addr:$src2)>; + (MOVHPSrm (v4i32 VR128:$src1), addr:$src2)>; def MOVLPSmr : PSI<0x13, MRMDestMem, (outs), (ins f64mem:$dst, VR128:$src), "movlps\t{$src, $dst|$dst, $src}", @@ -860,9 +860,9 @@ def MOVHLPSrr : PSI<0x12, MRMSrcReg, (outs VR128:$dst), let AddedComplexity = 20 in { def : Pat<(v4f32 (movddup VR128:$src, (undef))), - (MOVLHPSrr VR128:$src, VR128:$src)>; + (MOVLHPSrr (v4f32 VR128:$src), (v4f32 VR128:$src))>; def : Pat<(v2i64 (movddup VR128:$src, (undef))), - (MOVLHPSrr VR128:$src, VR128:$src)>; + (MOVLHPSrr (v2i64 VR128:$src), (v2i64 VR128:$src))>; } @@ -1011,9 +1011,9 @@ let Constraints = "$src1 = $dst" in { (memop addr:$src), imm:$cc))]>; } def : Pat<(v4i32 (X86cmpps (v4f32 VR128:$src1), VR128:$src2, imm:$cc)), - (CMPPSrri VR128:$src1, VR128:$src2, imm:$cc)>; + (CMPPSrri (v4f32 VR128:$src1), (v4f32 VR128:$src2), imm:$cc)>; def : Pat<(v4i32 (X86cmpps (v4f32 VR128:$src1), (memop addr:$src2), imm:$cc)), - (CMPPSrmi VR128:$src1, addr:$src2, imm:$cc)>; + (CMPPSrmi (v4f32 VR128:$src1), addr:$src2, imm:$cc)>; // Shuffle and unpack instructions let Constraints = "$src1 = $dst" in { @@ -1090,9 +1090,6 @@ def MOVNTDQ_64mr : PDI<0xE7, MRMDestMem, (outs), (ins f128mem:$dst, VR128:$src), "movntdq\t{$src, $dst|$dst, $src}", [(alignednontemporalstore (v2f64 VR128:$src), addr:$dst)]>; -def : Pat<(alignednontemporalstore (v2i64 VR128:$src), addr:$dst), - (MOVNTDQ_64mr VR128:$src, addr:$dst)>; - def MOVNTImr : I<0xC3, MRMDestMem, (outs), (ins i32mem:$dst, GR32:$src), "movnti\t{$src, $dst|$dst, $src}", [(nontemporalstore (i32 GR32:$src), addr:$dst)]>, @@ -1150,7 +1147,7 @@ def MOVSDrr : SDI<0x10, MRMSrcReg, // Extract the low 64-bit value from one vector and insert it into another. let AddedComplexity = 15 in def : Pat<(v2f64 (movl VR128:$src1, VR128:$src2)), - (MOVSDrr VR128:$src1, + (MOVSDrr (v2f64 VR128:$src1), (EXTRACT_SUBREG (v2f64 VR128:$src2), x86_subreg_sd))>; // Implicitly promote a 64-bit scalar to a vector. @@ -2394,9 +2391,6 @@ def MOVNTPDmr : PDI<0x2B, MRMDestMem, (outs), (ins f128mem:$dst, VR128:$src), def MOVNTDQmr : PDI<0xE7, MRMDestMem, (outs), (ins f128mem:$dst, VR128:$src), "movntdq\t{$src, $dst|$dst, $src}", [(alignednontemporalstore (v4f32 VR128:$src), addr:$dst)]>; - -def : Pat<(alignednontemporalstore (v4i32 VR128:$src), addr:$dst), - (MOVNTDQmr VR128:$src, addr:$dst)>; } // Flush cache diff --git a/lib/Target/X86/X86MCAsmInfo.cpp b/lib/Target/X86/X86MCAsmInfo.cpp index 250634f..9498810 100644 --- a/lib/Target/X86/X86MCAsmInfo.cpp +++ b/lib/Target/X86/X86MCAsmInfo.cpp @@ -68,7 +68,6 @@ X86MCAsmInfoDarwin::X86MCAsmInfoDarwin(const Triple &Triple) { // Exceptions handling ExceptionsType = ExceptionHandling::Dwarf; - AbsoluteEHSectionOffsets = false; } X86ELFMCAsmInfo::X86ELFMCAsmInfo(const Triple &Triple) { @@ -90,7 +89,6 @@ X86ELFMCAsmInfo::X86ELFMCAsmInfo(const Triple &Triple) { // Exceptions handling ExceptionsType = ExceptionHandling::Dwarf; - AbsoluteEHSectionOffsets = false; } MCSection *X86ELFMCAsmInfo::getNonexecutableStackSection(MCContext &Ctx) const { diff --git a/lib/Target/X86/X86RegisterInfo.cpp b/lib/Target/X86/X86RegisterInfo.cpp index 946d6b2..cdb579c 100644 --- a/lib/Target/X86/X86RegisterInfo.cpp +++ b/lib/Target/X86/X86RegisterInfo.cpp @@ -589,7 +589,7 @@ eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, unsigned X86RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, - int SPAdj, int *Value, + int SPAdj, FrameIndexValue *Value, RegScavenger *RS) const{ assert(SPAdj == 0 && "Unexpected"); @@ -1057,7 +1057,8 @@ void X86RegisterInfo::emitPrologue(MachineFunction &MF) const { BuildMI(MBB, MBBI, DL, TII.get(X86::MOV32ri), X86::EAX) .addImm(NumBytes); BuildMI(MBB, MBBI, DL, TII.get(X86::CALLpcrel32)) - .addExternalSymbol("_alloca"); + .addExternalSymbol("_alloca") + .addReg(StackPtr, RegState::Define | RegState::Implicit); } else { // Save EAX BuildMI(MBB, MBBI, DL, TII.get(X86::PUSH32r)) @@ -1068,7 +1069,8 @@ void X86RegisterInfo::emitPrologue(MachineFunction &MF) const { BuildMI(MBB, MBBI, DL, TII.get(X86::MOV32ri), X86::EAX) .addImm(NumBytes - 4); BuildMI(MBB, MBBI, DL, TII.get(X86::CALLpcrel32)) - .addExternalSymbol("_alloca"); + .addExternalSymbol("_alloca") + .addReg(StackPtr, RegState::Define | RegState::Implicit); // Restore EAX MachineInstr *MI = addRegOffset(BuildMI(MF, DL, TII.get(X86::MOV32rm), diff --git a/lib/Target/X86/X86RegisterInfo.h b/lib/Target/X86/X86RegisterInfo.h index e4bdb4e..12b2f3e 100644 --- a/lib/Target/X86/X86RegisterInfo.h +++ b/lib/Target/X86/X86RegisterInfo.h @@ -143,7 +143,7 @@ public: MachineBasicBlock::iterator MI) const; unsigned eliminateFrameIndex(MachineBasicBlock::iterator MI, - int SPAdj, int *Value = NULL, + int SPAdj, FrameIndexValue *Value = NULL, RegScavenger *RS = NULL) const; void processFunctionBeforeCalleeSavedScan(MachineFunction &MF, diff --git a/lib/Target/X86/X86TargetObjectFile.cpp b/lib/Target/X86/X86TargetObjectFile.cpp index 29a0be5..c80ae19 100644 --- a/lib/Target/X86/X86TargetObjectFile.cpp +++ b/lib/Target/X86/X86TargetObjectFile.cpp @@ -20,14 +20,19 @@ using namespace dwarf; const MCExpr *X8664_MachoTargetObjectFile:: getSymbolForDwarfGlobalReference(const GlobalValue *GV, Mangler *Mang, - MachineModuleInfo *MMI, unsigned Encoding) const { + MachineModuleInfo *MMI, + unsigned Encoding) const { // On Darwin/X86-64, we can reference dwarf symbols with foo@GOTPCREL+4, which // is an indirect pc-relative reference. if (Encoding & (DW_EH_PE_indirect | DW_EH_PE_pcrel)) { SmallString<128> Name; Mang->getNameWithPrefix(Name, GV, false); - const MCSymbol *Sym = getContext().GetOrCreateSymbol(Name); + const MCSymbol *Sym; + if (GV->hasPrivateLinkage()) + Sym = getContext().GetOrCreateTemporarySymbol(Name); + else + Sym = getContext().GetOrCreateSymbol(Name); const MCExpr *Res = X86MCTargetExpr::Create(Sym, X86MCTargetExpr::GOTPCREL, getContext()); const MCExpr *Four = MCConstantExpr::Create(4, getContext()); diff --git a/lib/Target/XCore/XCoreISelDAGToDAG.cpp b/lib/Target/XCore/XCoreISelDAGToDAG.cpp index b1ab132..29a6ab7 100644 --- a/lib/Target/XCore/XCoreISelDAGToDAG.cpp +++ b/lib/Target/XCore/XCoreISelDAGToDAG.cpp @@ -208,6 +208,24 @@ SDNode *XCoreDAGToDAGISel::Select(SDNode *N) { return CurDAG->getMachineNode(XCore::LSUB_l5r, dl, MVT::i32, MVT::i32, Ops, 3); } + case XCoreISD::MACCU: { + SDValue Ops[] = { N->getOperand(0), N->getOperand(1), + N->getOperand(2), N->getOperand(3) }; + return CurDAG->getMachineNode(XCore::MACCU_l4r, dl, MVT::i32, MVT::i32, + Ops, 4); + } + case XCoreISD::MACCS: { + SDValue Ops[] = { N->getOperand(0), N->getOperand(1), + N->getOperand(2), N->getOperand(3) }; + return CurDAG->getMachineNode(XCore::MACCS_l4r, dl, MVT::i32, MVT::i32, + Ops, 4); + } + case XCoreISD::LMUL: { + SDValue Ops[] = { N->getOperand(0), N->getOperand(1), + N->getOperand(2), N->getOperand(3) }; + return CurDAG->getMachineNode(XCore::LMUL_l6r, dl, MVT::i32, MVT::i32, + Ops, 4); + } // Other cases are autogenerated. } } diff --git a/lib/Target/XCore/XCoreISelLowering.cpp b/lib/Target/XCore/XCoreISelLowering.cpp index e6515d8..8249219 100644 --- a/lib/Target/XCore/XCoreISelLowering.cpp +++ b/lib/Target/XCore/XCoreISelLowering.cpp @@ -54,9 +54,12 @@ getTargetNodeName(unsigned Opcode) const case XCoreISD::RETSP : return "XCoreISD::RETSP"; case XCoreISD::LADD : return "XCoreISD::LADD"; case XCoreISD::LSUB : return "XCoreISD::LSUB"; + case XCoreISD::LMUL : return "XCoreISD::LMUL"; + case XCoreISD::MACCU : return "XCoreISD::MACCU"; + case XCoreISD::MACCS : return "XCoreISD::MACCS"; case XCoreISD::BR_JT : return "XCoreISD::BR_JT"; case XCoreISD::BR_JT32 : return "XCoreISD::BR_JT32"; - default : return NULL; + default : return NULL; } } @@ -96,6 +99,8 @@ XCoreTargetLowering::XCoreTargetLowering(XCoreTargetMachine &XTM) // 64bit setOperationAction(ISD::ADD, MVT::i64, Custom); setOperationAction(ISD::SUB, MVT::i64, Custom); + setOperationAction(ISD::SMUL_LOHI, MVT::i32, Custom); + setOperationAction(ISD::UMUL_LOHI, MVT::i32, Custom); setOperationAction(ISD::MULHS, MVT::i32, Expand); setOperationAction(ISD::MULHU, MVT::i32, Expand); setOperationAction(ISD::SHL_PARTS, MVT::i32, Expand); @@ -149,6 +154,7 @@ XCoreTargetLowering::XCoreTargetLowering(XCoreTargetMachine &XTM) // We have target-specific dag combine patterns for the following nodes: setTargetDAGCombine(ISD::STORE); + setTargetDAGCombine(ISD::ADD); } SDValue XCoreTargetLowering:: @@ -165,6 +171,8 @@ LowerOperation(SDValue Op, SelectionDAG &DAG) { case ISD::SELECT_CC: return LowerSELECT_CC(Op, DAG); case ISD::VAARG: return LowerVAARG(Op, DAG); case ISD::VASTART: return LowerVASTART(Op, DAG); + case ISD::SMUL_LOHI: return LowerSMUL_LOHI(Op, DAG); + case ISD::UMUL_LOHI: return LowerUMUL_LOHI(Op, DAG); // FIXME: Remove these when LegalizeDAGTypes lands. case ISD::ADD: case ISD::SUB: return ExpandADDSUB(Op.getNode(), DAG); @@ -542,11 +550,171 @@ LowerSTORE(SDValue Op, SelectionDAG &DAG) } SDValue XCoreTargetLowering:: +LowerSMUL_LOHI(SDValue Op, SelectionDAG &DAG) +{ + assert(Op.getValueType() == MVT::i32 && Op.getOpcode() == ISD::SMUL_LOHI && + "Unexpected operand to lower!"); + DebugLoc dl = Op.getDebugLoc(); + SDValue LHS = Op.getOperand(0); + SDValue RHS = Op.getOperand(1); + SDValue Zero = DAG.getConstant(0, MVT::i32); + SDValue Hi = DAG.getNode(XCoreISD::MACCS, dl, + DAG.getVTList(MVT::i32, MVT::i32), Zero, Zero, + LHS, RHS); + SDValue Lo(Hi.getNode(), 1); + SDValue Ops[] = { Lo, Hi }; + return DAG.getMergeValues(Ops, 2, dl); +} + +SDValue XCoreTargetLowering:: +LowerUMUL_LOHI(SDValue Op, SelectionDAG &DAG) +{ + assert(Op.getValueType() == MVT::i32 && Op.getOpcode() == ISD::UMUL_LOHI && + "Unexpected operand to lower!"); + DebugLoc dl = Op.getDebugLoc(); + SDValue LHS = Op.getOperand(0); + SDValue RHS = Op.getOperand(1); + SDValue Zero = DAG.getConstant(0, MVT::i32); + SDValue Hi = DAG.getNode(XCoreISD::LMUL, dl, + DAG.getVTList(MVT::i32, MVT::i32), LHS, RHS, + Zero, Zero); + SDValue Lo(Hi.getNode(), 1); + SDValue Ops[] = { Lo, Hi }; + return DAG.getMergeValues(Ops, 2, dl); +} + +/// isADDADDMUL - Return whether Op is in a form that is equivalent to +/// add(add(mul(x,y),a),b). If requireIntermediatesHaveOneUse is true then +/// each intermediate result in the calculation must also have a single use. +/// If the Op is in the correct form the constituent parts are written to Mul0, +/// Mul1, Addend0 and Addend1. +static bool +isADDADDMUL(SDValue Op, SDValue &Mul0, SDValue &Mul1, SDValue &Addend0, + SDValue &Addend1, bool requireIntermediatesHaveOneUse) +{ + if (Op.getOpcode() != ISD::ADD) + return false; + SDValue N0 = Op.getOperand(0); + SDValue N1 = Op.getOperand(1); + SDValue AddOp; + SDValue OtherOp; + if (N0.getOpcode() == ISD::ADD) { + AddOp = N0; + OtherOp = N1; + } else if (N1.getOpcode() == ISD::ADD) { + AddOp = N1; + OtherOp = N0; + } else { + return false; + } + if (requireIntermediatesHaveOneUse && !AddOp.hasOneUse()) + return false; + if (OtherOp.getOpcode() == ISD::MUL) { + // add(add(a,b),mul(x,y)) + if (requireIntermediatesHaveOneUse && !OtherOp.hasOneUse()) + return false; + Mul0 = OtherOp.getOperand(0); + Mul1 = OtherOp.getOperand(1); + Addend0 = AddOp.getOperand(0); + Addend1 = AddOp.getOperand(1); + return true; + } + if (AddOp.getOperand(0).getOpcode() == ISD::MUL) { + // add(add(mul(x,y),a),b) + if (requireIntermediatesHaveOneUse && !AddOp.getOperand(0).hasOneUse()) + return false; + Mul0 = AddOp.getOperand(0).getOperand(0); + Mul1 = AddOp.getOperand(0).getOperand(1); + Addend0 = AddOp.getOperand(1); + Addend1 = OtherOp; + return true; + } + if (AddOp.getOperand(1).getOpcode() == ISD::MUL) { + // add(add(a,mul(x,y)),b) + if (requireIntermediatesHaveOneUse && !AddOp.getOperand(1).hasOneUse()) + return false; + Mul0 = AddOp.getOperand(1).getOperand(0); + Mul1 = AddOp.getOperand(1).getOperand(1); + Addend0 = AddOp.getOperand(0); + Addend1 = OtherOp; + return true; + } + return false; +} + +SDValue XCoreTargetLowering:: +TryExpandADDWithMul(SDNode *N, SelectionDAG &DAG) +{ + SDValue Mul; + SDValue Other; + if (N->getOperand(0).getOpcode() == ISD::MUL) { + Mul = N->getOperand(0); + Other = N->getOperand(1); + } else if (N->getOperand(1).getOpcode() == ISD::MUL) { + Mul = N->getOperand(1); + Other = N->getOperand(0); + } else { + return SDValue(); + } + DebugLoc dl = N->getDebugLoc(); + SDValue LL, RL, AddendL, AddendH; + LL = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, + Mul.getOperand(0), DAG.getConstant(0, MVT::i32)); + RL = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, + Mul.getOperand(1), DAG.getConstant(0, MVT::i32)); + AddendL = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, + Other, DAG.getConstant(0, MVT::i32)); + AddendH = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, + Other, DAG.getConstant(1, MVT::i32)); + APInt HighMask = APInt::getHighBitsSet(64, 32); + unsigned LHSSB = DAG.ComputeNumSignBits(Mul.getOperand(0)); + unsigned RHSSB = DAG.ComputeNumSignBits(Mul.getOperand(1)); + if (DAG.MaskedValueIsZero(Mul.getOperand(0), HighMask) && + DAG.MaskedValueIsZero(Mul.getOperand(1), HighMask)) { + // The inputs are both zero-extended. + SDValue Hi = DAG.getNode(XCoreISD::MACCU, dl, + DAG.getVTList(MVT::i32, MVT::i32), AddendH, + AddendL, LL, RL); + SDValue Lo(Hi.getNode(), 1); + return DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, Lo, Hi); + } + if (LHSSB > 32 && RHSSB > 32) { + // The inputs are both sign-extended. + SDValue Hi = DAG.getNode(XCoreISD::MACCS, dl, + DAG.getVTList(MVT::i32, MVT::i32), AddendH, + AddendL, LL, RL); + SDValue Lo(Hi.getNode(), 1); + return DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, Lo, Hi); + } + SDValue LH, RH; + LH = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, + Mul.getOperand(0), DAG.getConstant(1, MVT::i32)); + RH = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, + Mul.getOperand(1), DAG.getConstant(1, MVT::i32)); + SDValue Hi = DAG.getNode(XCoreISD::MACCU, dl, + DAG.getVTList(MVT::i32, MVT::i32), AddendH, + AddendL, LL, RL); + SDValue Lo(Hi.getNode(), 1); + RH = DAG.getNode(ISD::MUL, dl, MVT::i32, LL, RH); + LH = DAG.getNode(ISD::MUL, dl, MVT::i32, LH, RL); + Hi = DAG.getNode(ISD::ADD, dl, MVT::i32, Hi, RH); + Hi = DAG.getNode(ISD::ADD, dl, MVT::i32, Hi, LH); + return DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, Lo, Hi); +} + +SDValue XCoreTargetLowering:: ExpandADDSUB(SDNode *N, SelectionDAG &DAG) { assert(N->getValueType(0) == MVT::i64 && (N->getOpcode() == ISD::ADD || N->getOpcode() == ISD::SUB) && "Unknown operand to lower!"); + + if (N->getOpcode() == ISD::ADD) { + SDValue Result = TryExpandADDWithMul(N, DAG); + if (Result.getNode() != 0) + return Result; + } + DebugLoc dl = N->getDebugLoc(); // Extract components @@ -1097,6 +1265,97 @@ SDValue XCoreTargetLowering::PerformDAGCombine(SDNode *N, DebugLoc dl = N->getDebugLoc(); switch (N->getOpcode()) { default: break; + case XCoreISD::LADD: { + SDValue N0 = N->getOperand(0); + SDValue N1 = N->getOperand(1); + SDValue N2 = N->getOperand(2); + ConstantSDNode *N0C = dyn_cast<ConstantSDNode>(N0); + ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N1); + EVT VT = N0.getValueType(); + + // canonicalize constant to RHS + if (N0C && !N1C) + return DAG.getNode(XCoreISD::LADD, dl, DAG.getVTList(VT, VT), N1, N0, N2); + + // fold (ladd 0, 0, x) -> 0, x & 1 + if (N0C && N0C->isNullValue() && N1C && N1C->isNullValue()) { + SDValue Carry = DAG.getConstant(0, VT); + SDValue Result = DAG.getNode(ISD::AND, dl, VT, N2, + DAG.getConstant(1, VT)); + SDValue Ops [] = { Carry, Result }; + return DAG.getMergeValues(Ops, 2, dl); + } + + // fold (ladd x, 0, y) -> 0, add x, y iff carry is unused and y has only the + // low bit set + if (N1C && N1C->isNullValue() && N->hasNUsesOfValue(0, 0)) { + APInt KnownZero, KnownOne; + APInt Mask = APInt::getHighBitsSet(VT.getSizeInBits(), + VT.getSizeInBits() - 1); + DAG.ComputeMaskedBits(N2, Mask, KnownZero, KnownOne); + if (KnownZero == Mask) { + SDValue Carry = DAG.getConstant(0, VT); + SDValue Result = DAG.getNode(ISD::ADD, dl, VT, N0, N2); + SDValue Ops [] = { Carry, Result }; + return DAG.getMergeValues(Ops, 2, dl); + } + } + } + break; + case XCoreISD::LSUB: { + SDValue N0 = N->getOperand(0); + SDValue N1 = N->getOperand(1); + SDValue N2 = N->getOperand(2); + ConstantSDNode *N0C = dyn_cast<ConstantSDNode>(N0); + ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N1); + EVT VT = N0.getValueType(); + + // fold (lsub 0, 0, x) -> x, -x iff x has only the low bit set + if (N0C && N0C->isNullValue() && N1C && N1C->isNullValue()) { + APInt KnownZero, KnownOne; + APInt Mask = APInt::getHighBitsSet(VT.getSizeInBits(), + VT.getSizeInBits() - 1); + DAG.ComputeMaskedBits(N2, Mask, KnownZero, KnownOne); + if (KnownZero == Mask) { + SDValue Borrow = N2; + SDValue Result = DAG.getNode(ISD::SUB, dl, VT, + DAG.getConstant(0, VT), N2); + SDValue Ops [] = { Borrow, Result }; + return DAG.getMergeValues(Ops, 2, dl); + } + } + + // fold (lsub x, 0, y) -> 0, sub x, y iff borrow is unused and y has only the + // low bit set + if (N1C && N1C->isNullValue() && N->hasNUsesOfValue(0, 0)) { + APInt KnownZero, KnownOne; + APInt Mask = APInt::getHighBitsSet(VT.getSizeInBits(), + VT.getSizeInBits() - 1); + DAG.ComputeMaskedBits(N2, Mask, KnownZero, KnownOne); + if (KnownZero == Mask) { + SDValue Borrow = DAG.getConstant(0, VT); + SDValue Result = DAG.getNode(ISD::SUB, dl, VT, N0, N2); + SDValue Ops [] = { Borrow, Result }; + return DAG.getMergeValues(Ops, 2, dl); + } + } + } + break; + case ISD::ADD: { + // Fold expressions such as add(add(mul(x,y),a),b) -> lmul(x, y, a, b). + // This is only profitable if the intermediate results are unused + // elsewhere. + SDValue Mul0, Mul1, Addend0, Addend1; + if (isADDADDMUL(SDValue(N, 0), Mul0, Mul1, Addend0, Addend1, true)) { + SDValue Zero = DAG.getConstant(0, MVT::i32); + SDValue Ignored = DAG.getNode(XCoreISD::LMUL, dl, + DAG.getVTList(MVT::i32, MVT::i32), Mul0, + Mul1, Addend0, Addend1); + SDValue Result(Ignored.getNode(), 1); + return Result; + } + } + break; case ISD::STORE: { // Replace unaligned store of unaligned load with memmove. StoreSDNode *ST = cast<StoreSDNode>(N); @@ -1137,6 +1396,27 @@ SDValue XCoreTargetLowering::PerformDAGCombine(SDNode *N, return SDValue(); } +void XCoreTargetLowering::computeMaskedBitsForTargetNode(const SDValue Op, + const APInt &Mask, + APInt &KnownZero, + APInt &KnownOne, + const SelectionDAG &DAG, + unsigned Depth) const { + KnownZero = KnownOne = APInt(Mask.getBitWidth(), 0); + switch (Op.getOpcode()) { + default: break; + case XCoreISD::LADD: + case XCoreISD::LSUB: + if (Op.getResNo() == 0) { + // Top bits of carry / borrow are clear. + KnownZero = APInt::getHighBitsSet(Mask.getBitWidth(), + Mask.getBitWidth() - 1); + KnownZero &= Mask; + } + break; + } +} + //===----------------------------------------------------------------------===// // Addressing mode description hooks //===----------------------------------------------------------------------===// diff --git a/lib/Target/XCore/XCoreISelLowering.h b/lib/Target/XCore/XCoreISelLowering.h index 0c638af..f597780 100644 --- a/lib/Target/XCore/XCoreISelLowering.h +++ b/lib/Target/XCore/XCoreISelLowering.h @@ -54,6 +54,15 @@ namespace llvm { // Corresponds to LSUB instruction LSUB, + // Corresponds to LMUL instruction + LMUL, + + // Corresponds to MACCU instruction + MACCU, + + // Corresponds to MACCS instruction + MACCS, + // Jumptable branch. BR_JT, @@ -132,6 +141,8 @@ namespace llvm { SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG); SDValue LowerVAARG(SDValue Op, SelectionDAG &DAG); SDValue LowerVASTART(SDValue Op, SelectionDAG &DAG); + SDValue LowerUMUL_LOHI(SDValue Op, SelectionDAG &DAG); + SDValue LowerSMUL_LOHI(SDValue Op, SelectionDAG &DAG); SDValue LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG); // Inline asm support @@ -140,10 +151,18 @@ namespace llvm { EVT VT) const; // Expand specifics + SDValue TryExpandADDWithMul(SDNode *Op, SelectionDAG &DAG); SDValue ExpandADDSUB(SDNode *Op, SelectionDAG &DAG); virtual SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const; + virtual void computeMaskedBitsForTargetNode(const SDValue Op, + const APInt &Mask, + APInt &KnownZero, + APInt &KnownOne, + const SelectionDAG &DAG, + unsigned Depth = 0) const; + virtual SDValue LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, diff --git a/lib/Target/XCore/XCoreRegisterInfo.cpp b/lib/Target/XCore/XCoreRegisterInfo.cpp index c7c8c7b..0ab312e 100644 --- a/lib/Target/XCore/XCoreRegisterInfo.cpp +++ b/lib/Target/XCore/XCoreRegisterInfo.cpp @@ -173,7 +173,7 @@ eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, unsigned XCoreRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, - int SPAdj, int *Value, + int SPAdj, FrameIndexValue *Value, RegScavenger *RS) const { assert(SPAdj == 0 && "Unexpected"); MachineInstr &MI = *II; diff --git a/lib/Target/XCore/XCoreRegisterInfo.h b/lib/Target/XCore/XCoreRegisterInfo.h index 8ab1750..5bdd059 100644 --- a/lib/Target/XCore/XCoreRegisterInfo.h +++ b/lib/Target/XCore/XCoreRegisterInfo.h @@ -58,7 +58,7 @@ public: MachineBasicBlock::iterator I) const; unsigned eliminateFrameIndex(MachineBasicBlock::iterator II, - int SPAdj, int *Value = NULL, + int SPAdj, FrameIndexValue *Value = NULL, RegScavenger *RS = NULL) const; void processFunctionBeforeCalleeSavedScan(MachineFunction &MF, diff --git a/lib/Transforms/IPO/InlineAlways.cpp b/lib/Transforms/IPO/InlineAlways.cpp index f11ecae..bc8028c 100644 --- a/lib/Transforms/IPO/InlineAlways.cpp +++ b/lib/Transforms/IPO/InlineAlways.cpp @@ -45,7 +45,10 @@ namespace { return CA.getInlineFudgeFactor(CS); } void resetCachedCostInfo(Function *Caller) { - return CA.resetCachedCostInfo(Caller); + CA.resetCachedCostInfo(Caller); + } + void growCachedCostInfo(Function* Caller, Function* Callee) { + CA.growCachedCostInfo(Caller, Callee); } virtual bool doFinalization(CallGraph &CG) { return removeDeadFunctions(CG, &NeverInline); diff --git a/lib/Transforms/IPO/InlineSimple.cpp b/lib/Transforms/IPO/InlineSimple.cpp index 598043d..46cf4b2 100644 --- a/lib/Transforms/IPO/InlineSimple.cpp +++ b/lib/Transforms/IPO/InlineSimple.cpp @@ -45,6 +45,9 @@ namespace { void resetCachedCostInfo(Function *Caller) { CA.resetCachedCostInfo(Caller); } + void growCachedCostInfo(Function* Caller, Function* Callee) { + CA.growCachedCostInfo(Caller, Callee); + } virtual bool doInitialization(CallGraph &CG); }; } diff --git a/lib/Transforms/IPO/Inliner.cpp b/lib/Transforms/IPO/Inliner.cpp index 752a97c..03ec72c 100644 --- a/lib/Transforms/IPO/Inliner.cpp +++ b/lib/Transforms/IPO/Inliner.cpp @@ -219,8 +219,10 @@ bool Inliner::shouldInline(CallSite CS) { Function *Caller = CS.getCaller(); int CurrentThreshold = getInlineThreshold(CS); float FudgeFactor = getInlineFudgeFactor(CS); - if (Cost >= (int)(CurrentThreshold * FudgeFactor)) { + int AdjThreshold = (int)(CurrentThreshold * FudgeFactor); + if (Cost >= AdjThreshold) { DEBUG(dbgs() << " NOT Inlining: cost=" << Cost + << ", thres=" << AdjThreshold << ", Call: " << *CS.getInstruction() << "\n"); return false; } @@ -285,6 +287,7 @@ bool Inliner::shouldInline(CallSite CS) { } DEBUG(dbgs() << " Inlining: cost=" << Cost + << ", thres=" << AdjThreshold << ", Call: " << *CS.getInstruction() << '\n'); return true; } @@ -366,6 +369,8 @@ bool Inliner::runOnSCC(std::vector<CallGraphNode*> &SCC) { CG[Caller]->removeCallEdgeFor(CS); CS.getInstruction()->eraseFromParent(); ++NumCallsDeleted; + // Update the cached cost info with the missing call + growCachedCostInfo(Caller, NULL); } else { // We can only inline direct calls to non-declarations. if (Callee == 0 || Callee->isDeclaration()) continue; @@ -379,6 +384,9 @@ bool Inliner::runOnSCC(std::vector<CallGraphNode*> &SCC) { if (!InlineCallIfPossible(CS, CG, TD, InlinedArrayAllocas)) continue; ++NumInlined; + + // Update the cached cost info with the inlined call. + growCachedCostInfo(Caller, Callee); } // If we inlined or deleted the last possible call site to the function, @@ -404,11 +412,6 @@ bool Inliner::runOnSCC(std::vector<CallGraphNode*> &SCC) { delete CG.removeFunctionFromModule(CalleeNode); ++NumDeleted; } - - // Remove any cached cost info for this caller, as inlining the - // callee has increased the size of the caller (which may be the - // same as the callee). - resetCachedCostInfo(Caller); // Remove this call site from the list. If possible, use // swap/pop_back for efficiency, but do not use it if doing so would diff --git a/lib/Transforms/InstCombine/InstCombine.h b/lib/Transforms/InstCombine/InstCombine.h index 07fb15e..bd06499 100644 --- a/lib/Transforms/InstCombine/InstCombine.h +++ b/lib/Transforms/InstCombine/InstCombine.h @@ -207,6 +207,7 @@ private: const Type *Ty); Instruction *visitCallSite(CallSite CS); + Instruction *tryOptimizeCall(CallInst *CI, const TargetData *TD); bool transformConstExprCastCall(CallSite CS); Instruction *transformCallThroughTrampoline(CallSite CS); Instruction *transformZExtICmp(ICmpInst *ICI, Instruction &CI, diff --git a/lib/Transforms/InstCombine/InstCombineCalls.cpp b/lib/Transforms/InstCombine/InstCombineCalls.cpp index a241f169..0582210 100644 --- a/lib/Transforms/InstCombine/InstCombineCalls.cpp +++ b/lib/Transforms/InstCombine/InstCombineCalls.cpp @@ -16,6 +16,7 @@ #include "llvm/Support/CallSite.h" #include "llvm/Target/TargetData.h" #include "llvm/Analysis/MemoryBuiltins.h" +#include "llvm/Transforms/Utils/BuildLibCalls.h" using namespace llvm; /// getPromotedType - Return the specified type promoted as it would be to pass @@ -336,6 +337,16 @@ Instruction *InstCombiner::visitCallInst(CallInst &CI) { } return ReplaceInstUsesWith(CI, ConstantInt::get(ReturnTy, AllocaSize)); } + } else if (CallInst *MI = extractMallocCall(Op1)) { + const Type* MallocType = getMallocAllocatedType(MI); + // Get alloca size. + if (MallocType && MallocType->isSized()) { + if (Value *NElems = getMallocArraySize(MI, TD, true)) { + if (ConstantInt *NElements = dyn_cast<ConstantInt>(NElems)) + return ReplaceInstUsesWith(CI, ConstantInt::get(ReturnTy, + (NElements->getZExtValue() * TD->getTypeAllocSize(MallocType)))); + } + } } else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(Op1)) { // Only handle constant GEPs here. if (CE->getOpcode() != Instruction::GetElementPtr) break; @@ -347,7 +358,7 @@ Instruction *InstCombiner::visitCallInst(CallInst &CI) { Operand = Operand->stripPointerCasts(); if (GlobalVariable *GV = dyn_cast<GlobalVariable>(Operand)) if (!GV->hasDefinitiveInitializer()) break; - + // Get what we're pointing to and its size. const PointerType *BaseType = cast<PointerType>(Operand->getType()); @@ -370,7 +381,7 @@ Instruction *InstCombiner::visitCallInst(CallInst &CI) { Constant *RetVal = ConstantInt::get(ReturnTy, Size-Offset); return ReplaceInstUsesWith(CI, RetVal); - } + } // Do not return "I don't know" here. Later optimization passes could // make it possible to evaluate objectsize to a constant. @@ -740,6 +751,122 @@ static bool isSafeToEliminateVarargsCast(const CallSite CS, return true; } +// Try to fold some different type of calls here. +// Currently we're only working with the checking functions, memcpy_chk, +// mempcpy_chk, memmove_chk, memset_chk, strcpy_chk, stpcpy_chk, strncpy_chk, +// strcat_chk and strncat_chk. +Instruction *InstCombiner::tryOptimizeCall(CallInst *CI, const TargetData *TD) { + if (CI->getCalledFunction() == 0) return 0; + + StringRef Name = CI->getCalledFunction()->getName(); + BasicBlock *BB = CI->getParent(); + IRBuilder<> B(CI->getParent()->getContext()); + + // Set the builder to the instruction after the call. + B.SetInsertPoint(BB, CI); + + if (Name == "__memcpy_chk") { + ConstantInt *SizeCI = dyn_cast<ConstantInt>(CI->getOperand(4)); + if (!SizeCI) + return 0; + ConstantInt *SizeArg = dyn_cast<ConstantInt>(CI->getOperand(3)); + if (!SizeArg) + return 0; + if (SizeCI->isAllOnesValue() || + SizeCI->getZExtValue() <= SizeArg->getZExtValue()) { + EmitMemCpy(CI->getOperand(1), CI->getOperand(2), CI->getOperand(3), + 1, B, TD); + return ReplaceInstUsesWith(*CI, CI->getOperand(1)); + } + return 0; + } + + // Should be similar to memcpy. + if (Name == "__mempcpy_chk") { + return 0; + } + + if (Name == "__memmove_chk") { + ConstantInt *SizeCI = dyn_cast<ConstantInt>(CI->getOperand(4)); + if (!SizeCI) + return 0; + ConstantInt *SizeArg = dyn_cast<ConstantInt>(CI->getOperand(3)); + if (!SizeArg) + return 0; + if (SizeCI->isAllOnesValue() || + SizeCI->getZExtValue() <= SizeArg->getZExtValue()) { + EmitMemMove(CI->getOperand(1), CI->getOperand(2), CI->getOperand(3), + 1, B, TD); + return ReplaceInstUsesWith(*CI, CI->getOperand(1)); + } + return 0; + } + + if (Name == "__memset_chk") { + ConstantInt *SizeCI = dyn_cast<ConstantInt>(CI->getOperand(4)); + if (!SizeCI) + return 0; + ConstantInt *SizeArg = dyn_cast<ConstantInt>(CI->getOperand(3)); + if (!SizeArg) + return 0; + if (SizeCI->isAllOnesValue() || + SizeCI->getZExtValue() <= SizeArg->getZExtValue()) { + Value *Val = B.CreateIntCast(CI->getOperand(2), B.getInt8Ty(), + false); + EmitMemSet(CI->getOperand(1), Val, CI->getOperand(3), B, TD); + return ReplaceInstUsesWith(*CI, CI->getOperand(1)); + } + return 0; + } + + if (Name == "__strcpy_chk") { + ConstantInt *SizeCI = dyn_cast<ConstantInt>(CI->getOperand(3)); + if (!SizeCI) + return 0; + // If a) we don't have any length information, or b) we know this will + // fit then just lower to a plain strcpy. Otherwise we'll keep our + // strcpy_chk call which may fail at runtime if the size is too long. + // TODO: It might be nice to get a maximum length out of the possible + // string lengths for varying. + if (SizeCI->isAllOnesValue() || + SizeCI->getZExtValue() >= GetStringLength(CI->getOperand(2))) { + Value *Ret = EmitStrCpy(CI->getOperand(1), CI->getOperand(2), B, TD); + return ReplaceInstUsesWith(*CI, Ret); + } + return 0; + } + + // Should be similar to strcpy. + if (Name == "__stpcpy_chk") { + return 0; + } + + if (Name == "__strncpy_chk") { + ConstantInt *SizeCI = dyn_cast<ConstantInt>(CI->getOperand(4)); + if (!SizeCI) + return 0; + ConstantInt *SizeArg = dyn_cast<ConstantInt>(CI->getOperand(3)); + if (!SizeArg) + return 0; + if (SizeCI->isAllOnesValue() || + SizeCI->getZExtValue() <= SizeArg->getZExtValue()) { + Value *Ret = EmitStrCpy(CI->getOperand(1), CI->getOperand(2), B, TD); + return ReplaceInstUsesWith(*CI, Ret); + } + return 0; + } + + if (Name == "__strcat_chk") { + return 0; + } + + if (Name == "__strncat_chk") { + return 0; + } + + return 0; +} + // visitCallSite - Improvements for call and invoke instructions. // Instruction *InstCombiner::visitCallSite(CallSite CS) { @@ -826,6 +953,16 @@ Instruction *InstCombiner::visitCallSite(CallSite CS) { Changed = true; } + // Try to optimize the call if possible, we require TargetData for most of + // this. None of these calls are seen as possibly dead so go ahead and + // delete the instruction now. + if (CallInst *CI = dyn_cast<CallInst>(CS.getInstruction())) { + Instruction *I = tryOptimizeCall(CI, TD); + // If we changed something return the result, etc. Otherwise let + // the fallthrough check. + if (I) return EraseInstFromFunction(*I); + } + return Changed ? CS.getInstruction() : 0; } diff --git a/lib/Transforms/Scalar/SimplifyLibCalls.cpp b/lib/Transforms/Scalar/SimplifyLibCalls.cpp index 86ddeac..05027ae 100644 --- a/lib/Transforms/Scalar/SimplifyLibCalls.cpp +++ b/lib/Transforms/Scalar/SimplifyLibCalls.cpp @@ -633,130 +633,6 @@ struct MemSetOpt : public LibCallOptimization { }; //===----------------------------------------------------------------------===// -// Object Size Checking Optimizations -//===----------------------------------------------------------------------===// - -//===---------------------------------------===// -// 'memcpy_chk' Optimizations - -struct MemCpyChkOpt : public LibCallOptimization { - virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) { - // These optimizations require TargetData. - if (!TD) return 0; - - const FunctionType *FT = Callee->getFunctionType(); - if (FT->getNumParams() != 4 || FT->getReturnType() != FT->getParamType(0) || - !FT->getParamType(0)->isPointerTy() || - !FT->getParamType(1)->isPointerTy() || - !FT->getParamType(3)->isIntegerTy() || - FT->getParamType(2) != TD->getIntPtrType(*Context)) - return 0; - - ConstantInt *ObjSizeCI = dyn_cast<ConstantInt>(CI->getOperand(4)); - if (!ObjSizeCI) - return 0; - ConstantInt *SizeCI = dyn_cast<ConstantInt>(CI->getOperand(3)); - if (ObjSizeCI->isAllOnesValue() || - (SizeCI && ObjSizeCI->getValue().uge(SizeCI->getValue()))) { - EmitMemCpy(CI->getOperand(1), CI->getOperand(2), - CI->getOperand(3), 1, B, TD); - return CI->getOperand(1); - } - - return 0; - } -}; - -//===---------------------------------------===// -// 'memset_chk' Optimizations - -struct MemSetChkOpt : public LibCallOptimization { - virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) { - // These optimizations require TargetData. - if (!TD) return 0; - - const FunctionType *FT = Callee->getFunctionType(); - if (FT->getNumParams() != 4 || FT->getReturnType() != FT->getParamType(0) || - !FT->getParamType(0)->isPointerTy() || - !FT->getParamType(1)->isIntegerTy() || - !FT->getParamType(3)->isIntegerTy() || - FT->getParamType(2) != TD->getIntPtrType(*Context)) - return 0; - - ConstantInt *ObjSizeCI = dyn_cast<ConstantInt>(CI->getOperand(4)); - if (!ObjSizeCI) - return 0; - ConstantInt *SizeCI = dyn_cast<ConstantInt>(CI->getOperand(3)); - if (ObjSizeCI->isAllOnesValue() || - (SizeCI && ObjSizeCI->getValue().uge(SizeCI->getValue()))) { - Value *Val = B.CreateIntCast(CI->getOperand(2), Type::getInt8Ty(*Context), - false); - EmitMemSet(CI->getOperand(1), Val, CI->getOperand(3), B, TD); - return CI->getOperand(1); - } - - return 0; - } -}; - -//===---------------------------------------===// -// 'memmove_chk' Optimizations - -struct MemMoveChkOpt : public LibCallOptimization { - virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) { - // These optimizations require TargetData. - if (!TD) return 0; - - const FunctionType *FT = Callee->getFunctionType(); - if (FT->getNumParams() != 4 || FT->getReturnType() != FT->getParamType(0) || - !FT->getParamType(0)->isPointerTy() || - !FT->getParamType(1)->isPointerTy() || - !FT->getParamType(3)->isIntegerTy() || - FT->getParamType(2) != TD->getIntPtrType(*Context)) - return 0; - - ConstantInt *ObjSizeCI = dyn_cast<ConstantInt>(CI->getOperand(4)); - if (!ObjSizeCI) - return 0; - ConstantInt *SizeCI = dyn_cast<ConstantInt>(CI->getOperand(3)); - if (ObjSizeCI->isAllOnesValue() || - (SizeCI && ObjSizeCI->getValue().uge(SizeCI->getValue()))) { - EmitMemMove(CI->getOperand(1), CI->getOperand(2), CI->getOperand(3), - 1, B, TD); - return CI->getOperand(1); - } - - return 0; - } -}; - -struct StrCpyChkOpt : public LibCallOptimization { - virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) { - const FunctionType *FT = Callee->getFunctionType(); - if (FT->getNumParams() != 3 || FT->getReturnType() != FT->getParamType(0) || - !FT->getParamType(0)->isPointerTy() || - !FT->getParamType(1)->isPointerTy()) - return 0; - - ConstantInt *ObjSizeCI = dyn_cast<ConstantInt>(CI->getOperand(3)); - if (!ObjSizeCI) - return 0; - - // If a) we don't have any length information, or b) we know this will - // fit then just lower to a plain strcpy. Otherwise we'll keep our - // strcpy_chk call which may fail at runtime if the size is too long. - // TODO: It might be nice to get a maximum length out of the possible - // string lengths for varying. - if (ObjSizeCI->isAllOnesValue() || - ObjSizeCI->getZExtValue() >= GetStringLength(CI->getOperand(2))) - return EmitStrCpy(CI->getOperand(1), CI->getOperand(2), B, TD); - - return 0; - } -}; - - -//===----------------------------------------------------------------------===// // Math Library Optimizations //===----------------------------------------------------------------------===// @@ -1298,10 +1174,6 @@ namespace { SPrintFOpt SPrintF; PrintFOpt PrintF; FWriteOpt FWrite; FPutsOpt FPuts; FPrintFOpt FPrintF; - // Object Size Checking - MemCpyChkOpt MemCpyChk; MemSetChkOpt MemSetChk; MemMoveChkOpt MemMoveChk; - StrCpyChkOpt StrCpyChk; - bool Modified; // This is only used by doInitialization. public: static char ID; // Pass identification @@ -1407,12 +1279,6 @@ void SimplifyLibCalls::InitOptimizations() { Optimizations["fwrite"] = &FWrite; Optimizations["fputs"] = &FPuts; Optimizations["fprintf"] = &FPrintF; - - // Object Size Checking - Optimizations["__memcpy_chk"] = &MemCpyChk; - Optimizations["__memset_chk"] = &MemSetChk; - Optimizations["__memmove_chk"] = &MemMoveChk; - Optimizations["__strcpy_chk"] = &StrCpyChk; } diff --git a/lib/Transforms/Utils/CloneFunction.cpp b/lib/Transforms/Utils/CloneFunction.cpp index c80827d..62fc2ec 100644 --- a/lib/Transforms/Utils/CloneFunction.cpp +++ b/lib/Transforms/Utils/CloneFunction.cpp @@ -336,14 +336,14 @@ ConstantFoldMappedInstruction(const Instruction *I) { static MDNode *UpdateInlinedAtInfo(MDNode *InsnMD, MDNode *TheCallMD) { DILocation ILoc(InsnMD); - if (ILoc.isNull()) return InsnMD; + if (!ILoc.Verify()) return InsnMD; DILocation CallLoc(TheCallMD); - if (CallLoc.isNull()) return InsnMD; + if (!CallLoc.Verify()) return InsnMD; DILocation OrigLocation = ILoc.getOrigLocation(); MDNode *NewLoc = TheCallMD; - if (!OrigLocation.isNull()) + if (OrigLocation.Verify()) NewLoc = UpdateInlinedAtInfo(OrigLocation.getNode(), TheCallMD); Value *MDVs[] = { diff --git a/lib/Transforms/Utils/LoopSimplify.cpp b/lib/Transforms/Utils/LoopSimplify.cpp index 924b744..584ec14 100644 --- a/lib/Transforms/Utils/LoopSimplify.cpp +++ b/lib/Transforms/Utils/LoopSimplify.cpp @@ -132,7 +132,7 @@ bool LoopSimplify::ProcessLoop(Loop *L, LPPassManager &LPM) { bool Changed = false; ReprocessLoop: - // Check to see that no blocks (other than the header) in this loop that has + // Check to see that no blocks (other than the header) in this loop have // predecessors that are not in the loop. This is not valid for natural // loops, but can occur if the blocks are unreachable. Since they are // unreachable we can just shamelessly delete those CFG edges! diff --git a/lib/VMCore/Metadata.cpp b/lib/VMCore/Metadata.cpp index a08c454..379aeb5 100644 --- a/lib/VMCore/Metadata.cpp +++ b/lib/VMCore/Metadata.cpp @@ -39,15 +39,6 @@ MDString *MDString::get(LLVMContext &Context, StringRef Str) { return S; } -MDString *MDString::get(LLVMContext &Context, const char *Str) { - LLVMContextImpl *pImpl = Context.pImpl; - StringMapEntry<MDString *> &Entry = - pImpl->MDStringCache.GetOrCreateValue(Str ? StringRef(Str) : StringRef()); - MDString *&S = Entry.getValue(); - if (!S) S = new MDString(Context, Entry.getKey()); - return S; -} - //===----------------------------------------------------------------------===// // MDNodeOperand implementation. // diff --git a/lib/VMCore/Verifier.cpp b/lib/VMCore/Verifier.cpp index 35625a5..721e96a 100644 --- a/lib/VMCore/Verifier.cpp +++ b/lib/VMCore/Verifier.cpp @@ -1525,6 +1525,15 @@ void Verifier::VerifyType(const Type *Ty) { VerifyType(ElTy); } } break; + case Type::UnionTyID: { + const UnionType *UTy = cast<UnionType>(Ty); + for (unsigned i = 0, e = UTy->getNumElements(); i != e; ++i) { + const Type *ElTy = UTy->getElementType(i); + Assert2(UnionType::isValidElementType(ElTy), + "Union type with invalid element type", ElTy, UTy); + VerifyType(ElTy); + } + } break; case Type::ArrayTyID: { const ArrayType *ATy = cast<ArrayType>(Ty); Assert1(ArrayType::isValidElementType(ATy->getElementType()), |