diff --git a/opts/COPYING b/opts/COPYING new file mode 100644 index 0000000..8647a56 --- /dev/null +++ b/opts/COPYING @@ -0,0 +1,20 @@ +Copyright (c) 2009 David Chisnall + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + diff --git a/opts/Debug/.dir b/opts/Debug/.dir new file mode 100644 index 0000000..25bc296 --- /dev/null +++ b/opts/Debug/.dir @@ -0,0 +1 @@ +Sun 13 Sep 2009 13:29:32 UTC diff --git a/opts/Debug/IvarPass.d b/opts/Debug/IvarPass.d new file mode 100644 index 0000000..376fe68 --- /dev/null +++ b/opts/Debug/IvarPass.d @@ -0,0 +1,192 @@ +/usr/home/theraven/llvm/lib/Transforms/GNUObjC/Debug/IvarPass.o \ + /usr/home/theraven/llvm/lib/Transforms/GNUObjC/Debug/IvarPass.d \ + /usr/home/theraven/llvm/lib/Transforms/GNUObjC/Debug/IvarPass.o: \ + IvarPass.cpp /usr/home/theraven/llvm/include/llvm/Pass.h \ + /usr/home/theraven/llvm/include/llvm/Support/DataTypes.h \ + /usr/home/theraven/llvm/include/llvm/PassSupport.h \ + /usr/home/theraven/llvm/include/llvm/PassAnalysisSupport.h \ + /usr/home/theraven/llvm/include/llvm/ADT/SmallVector.h \ + /usr/home/theraven/llvm/include/llvm/Support/type_traits.h \ + /usr/home/theraven/llvm/include/llvm/Function.h \ + /usr/home/theraven/llvm/include/llvm/GlobalValue.h \ + /usr/home/theraven/llvm/include/llvm/Constant.h \ + /usr/home/theraven/llvm/include/llvm/User.h \ + /usr/home/theraven/llvm/include/llvm/Value.h \ + /usr/home/theraven/llvm/include/llvm/AbstractTypeUser.h \ + /usr/home/theraven/llvm/include/llvm/Use.h \ + /usr/home/theraven/llvm/include/llvm/Support/Casting.h \ + /usr/home/theraven/llvm/include/llvm/ADT/PointerIntPair.h \ + /usr/home/theraven/llvm/include/llvm/Support/PointerLikeTypeTraits.h \ + /usr/home/theraven/llvm/include/llvm/Support/DataTypes.h \ + /usr/home/theraven/llvm/include/llvm/ADT/StringRef.h \ + /usr/home/theraven/llvm/include/llvm/ADT/Twine.h \ + /usr/home/theraven/llvm/include/llvm/ADT/StringRef.h \ + /usr/home/theraven/llvm/include/llvm/Support/DataTypes.h \ + /usr/home/theraven/llvm/include/llvm/CallingConv.h \ + /usr/home/theraven/llvm/include/llvm/BasicBlock.h \ + /usr/home/theraven/llvm/include/llvm/Instruction.h \ + /usr/home/theraven/llvm/include/llvm/ADT/ilist_node.h \ + /usr/home/theraven/llvm/include/llvm/Instruction.def \ + /usr/home/theraven/llvm/include/llvm/SymbolTableListTraits.h \ + /usr/home/theraven/llvm/include/llvm/ADT/ilist.h \ + /usr/home/theraven/llvm/include/llvm/Argument.h \ + /usr/home/theraven/llvm/include/llvm/Attributes.h \ + /usr/home/theraven/llvm/include/llvm/Support/MathExtras.h \ + /usr/home/theraven/llvm/include/llvm/Module.h \ + /usr/home/theraven/llvm/include/llvm/Function.h \ + /usr/home/theraven/llvm/include/llvm/GlobalVariable.h \ + /usr/home/theraven/llvm/include/llvm/OperandTraits.h \ + /usr/home/theraven/llvm/include/llvm/GlobalAlias.h \ + /usr/home/theraven/llvm/include/llvm/Metadata.h \ + /usr/home/theraven/llvm/include/llvm/Type.h \ + /usr/home/theraven/llvm/include/llvm/LLVMContext.h \ + /usr/home/theraven/llvm/include/llvm/System/Atomic.h \ + /usr/home/theraven/llvm/include/llvm/Support/DataTypes.h \ + /usr/home/theraven/llvm/include/llvm/ADT/GraphTraits.h \ + /usr/home/theraven/llvm/include/llvm/ADT/FoldingSet.h \ + /usr/home/theraven/llvm/include/llvm/ADT/SmallVector.h \ + /usr/home/theraven/llvm/include/llvm/ADT/SmallPtrSet.h \ + /usr/home/theraven/llvm/include/llvm/Support/ErrorHandling.h \ + /usr/home/theraven/llvm/include/llvm/Support/Compiler.h \ + /usr/home/theraven/llvm/include/llvm/Support/ValueHandle.h \ + /usr/home/theraven/llvm/include/llvm/ADT/DenseMapInfo.h \ + /usr/home/theraven/llvm/include/llvm/ADT/PointerIntPair.h \ + /usr/home/theraven/llvm/include/llvm/Value.h \ + /usr/home/theraven/llvm/include/llvm/Instructions.h \ + /usr/home/theraven/llvm/include/llvm/InstrTypes.h \ + /usr/home/theraven/llvm/include/llvm/Operator.h \ + /usr/home/theraven/llvm/include/llvm/Constants.h \ + /usr/home/theraven/llvm/include/llvm/ADT/APInt.h \ + /usr/home/theraven/llvm/include/llvm/Support/MathExtras.h \ + /usr/home/theraven/llvm/include/llvm/ADT/APFloat.h \ + /usr/home/theraven/llvm/include/llvm/ADT/APInt.h \ + /usr/home/theraven/llvm/include/llvm/DerivedTypes.h \ + /usr/home/theraven/llvm/include/llvm/GlobalAlias.h \ + /usr/home/theraven/llvm/include/llvm/GlobalVariable.h \ + /usr/home/theraven/llvm/include/llvm/Constants.h + +/usr/home/theraven/llvm/include/llvm/Pass.h: + +/usr/home/theraven/llvm/include/llvm/Support/DataTypes.h: + +/usr/home/theraven/llvm/include/llvm/PassSupport.h: + +/usr/home/theraven/llvm/include/llvm/PassAnalysisSupport.h: + +/usr/home/theraven/llvm/include/llvm/ADT/SmallVector.h: + +/usr/home/theraven/llvm/include/llvm/Support/type_traits.h: + +/usr/home/theraven/llvm/include/llvm/Function.h: + +/usr/home/theraven/llvm/include/llvm/GlobalValue.h: + +/usr/home/theraven/llvm/include/llvm/Constant.h: + +/usr/home/theraven/llvm/include/llvm/User.h: + +/usr/home/theraven/llvm/include/llvm/Value.h: + +/usr/home/theraven/llvm/include/llvm/AbstractTypeUser.h: + +/usr/home/theraven/llvm/include/llvm/Use.h: + +/usr/home/theraven/llvm/include/llvm/Support/Casting.h: + +/usr/home/theraven/llvm/include/llvm/ADT/PointerIntPair.h: + +/usr/home/theraven/llvm/include/llvm/Support/PointerLikeTypeTraits.h: + +/usr/home/theraven/llvm/include/llvm/Support/DataTypes.h: + +/usr/home/theraven/llvm/include/llvm/ADT/StringRef.h: + +/usr/home/theraven/llvm/include/llvm/ADT/Twine.h: + +/usr/home/theraven/llvm/include/llvm/ADT/StringRef.h: + +/usr/home/theraven/llvm/include/llvm/Support/DataTypes.h: + +/usr/home/theraven/llvm/include/llvm/CallingConv.h: + +/usr/home/theraven/llvm/include/llvm/BasicBlock.h: + +/usr/home/theraven/llvm/include/llvm/Instruction.h: + +/usr/home/theraven/llvm/include/llvm/ADT/ilist_node.h: + +/usr/home/theraven/llvm/include/llvm/Instruction.def: + +/usr/home/theraven/llvm/include/llvm/SymbolTableListTraits.h: + +/usr/home/theraven/llvm/include/llvm/ADT/ilist.h: + +/usr/home/theraven/llvm/include/llvm/Argument.h: + +/usr/home/theraven/llvm/include/llvm/Attributes.h: + +/usr/home/theraven/llvm/include/llvm/Support/MathExtras.h: + +/usr/home/theraven/llvm/include/llvm/Module.h: + +/usr/home/theraven/llvm/include/llvm/Function.h: + +/usr/home/theraven/llvm/include/llvm/GlobalVariable.h: + +/usr/home/theraven/llvm/include/llvm/OperandTraits.h: + +/usr/home/theraven/llvm/include/llvm/GlobalAlias.h: + +/usr/home/theraven/llvm/include/llvm/Metadata.h: + +/usr/home/theraven/llvm/include/llvm/Type.h: + +/usr/home/theraven/llvm/include/llvm/LLVMContext.h: + +/usr/home/theraven/llvm/include/llvm/System/Atomic.h: + +/usr/home/theraven/llvm/include/llvm/Support/DataTypes.h: + +/usr/home/theraven/llvm/include/llvm/ADT/GraphTraits.h: + +/usr/home/theraven/llvm/include/llvm/ADT/FoldingSet.h: + +/usr/home/theraven/llvm/include/llvm/ADT/SmallVector.h: + +/usr/home/theraven/llvm/include/llvm/ADT/SmallPtrSet.h: + +/usr/home/theraven/llvm/include/llvm/Support/ErrorHandling.h: + +/usr/home/theraven/llvm/include/llvm/Support/Compiler.h: + +/usr/home/theraven/llvm/include/llvm/Support/ValueHandle.h: + +/usr/home/theraven/llvm/include/llvm/ADT/DenseMapInfo.h: + +/usr/home/theraven/llvm/include/llvm/ADT/PointerIntPair.h: + +/usr/home/theraven/llvm/include/llvm/Value.h: + +/usr/home/theraven/llvm/include/llvm/Instructions.h: + +/usr/home/theraven/llvm/include/llvm/InstrTypes.h: + +/usr/home/theraven/llvm/include/llvm/Operator.h: + +/usr/home/theraven/llvm/include/llvm/Constants.h: + +/usr/home/theraven/llvm/include/llvm/ADT/APInt.h: + +/usr/home/theraven/llvm/include/llvm/Support/MathExtras.h: + +/usr/home/theraven/llvm/include/llvm/ADT/APFloat.h: + +/usr/home/theraven/llvm/include/llvm/ADT/APInt.h: + +/usr/home/theraven/llvm/include/llvm/DerivedTypes.h: + +/usr/home/theraven/llvm/include/llvm/GlobalAlias.h: + +/usr/home/theraven/llvm/include/llvm/GlobalVariable.h: + +/usr/home/theraven/llvm/include/llvm/Constants.h: diff --git a/opts/Debug/TypeFeedback.d b/opts/Debug/TypeFeedback.d new file mode 100644 index 0000000..5998b41 --- /dev/null +++ b/opts/Debug/TypeFeedback.d @@ -0,0 +1,186 @@ +/usr/home/theraven/llvm/lib/Transforms/GNUObjC/Debug/TypeFeedback.o \ + /usr/home/theraven/llvm/lib/Transforms/GNUObjC/Debug/TypeFeedback.d \ + /usr/home/theraven/llvm/lib/Transforms/GNUObjC/Debug/TypeFeedback.o: \ + TypeFeedback.cpp /usr/home/theraven/llvm/include/llvm/Constants.h \ + /usr/home/theraven/llvm/include/llvm/Constant.h \ + /usr/home/theraven/llvm/include/llvm/User.h \ + /usr/home/theraven/llvm/include/llvm/Value.h \ + /usr/home/theraven/llvm/include/llvm/AbstractTypeUser.h \ + /usr/home/theraven/llvm/include/llvm/Use.h \ + /usr/home/theraven/llvm/include/llvm/Support/Casting.h \ + /usr/home/theraven/llvm/include/llvm/ADT/PointerIntPair.h \ + /usr/home/theraven/llvm/include/llvm/Support/PointerLikeTypeTraits.h \ + /usr/home/theraven/llvm/include/llvm/Support/DataTypes.h \ + /usr/home/theraven/llvm/include/llvm/ADT/StringRef.h \ + /usr/home/theraven/llvm/include/llvm/ADT/Twine.h \ + /usr/home/theraven/llvm/include/llvm/ADT/StringRef.h \ + /usr/home/theraven/llvm/include/llvm/Support/DataTypes.h \ + /usr/home/theraven/llvm/include/llvm/Type.h \ + /usr/home/theraven/llvm/include/llvm/LLVMContext.h \ + /usr/home/theraven/llvm/include/llvm/Support/DataTypes.h \ + /usr/home/theraven/llvm/include/llvm/System/Atomic.h \ + /usr/home/theraven/llvm/include/llvm/Support/DataTypes.h \ + /usr/home/theraven/llvm/include/llvm/ADT/GraphTraits.h \ + /usr/home/theraven/llvm/include/llvm/OperandTraits.h \ + /usr/home/theraven/llvm/include/llvm/ADT/APInt.h \ + /usr/home/theraven/llvm/include/llvm/Support/MathExtras.h \ + /usr/home/theraven/llvm/include/llvm/ADT/APFloat.h \ + /usr/home/theraven/llvm/include/llvm/ADT/APInt.h \ + /usr/home/theraven/llvm/include/llvm/ADT/SmallVector.h \ + /usr/home/theraven/llvm/include/llvm/Support/type_traits.h \ + /usr/home/theraven/llvm/include/llvm/Pass.h \ + /usr/home/theraven/llvm/include/llvm/PassSupport.h \ + /usr/home/theraven/llvm/include/llvm/PassAnalysisSupport.h \ + /usr/home/theraven/llvm/include/llvm/Module.h \ + /usr/home/theraven/llvm/include/llvm/Function.h \ + /usr/home/theraven/llvm/include/llvm/GlobalValue.h \ + /usr/home/theraven/llvm/include/llvm/CallingConv.h \ + /usr/home/theraven/llvm/include/llvm/BasicBlock.h \ + /usr/home/theraven/llvm/include/llvm/Instruction.h \ + /usr/home/theraven/llvm/include/llvm/ADT/ilist_node.h \ + /usr/home/theraven/llvm/include/llvm/Instruction.def \ + /usr/home/theraven/llvm/include/llvm/SymbolTableListTraits.h \ + /usr/home/theraven/llvm/include/llvm/ADT/ilist.h \ + /usr/home/theraven/llvm/include/llvm/Argument.h \ + /usr/home/theraven/llvm/include/llvm/Attributes.h \ + /usr/home/theraven/llvm/include/llvm/Support/MathExtras.h \ + /usr/home/theraven/llvm/include/llvm/GlobalVariable.h \ + /usr/home/theraven/llvm/include/llvm/GlobalAlias.h \ + /usr/home/theraven/llvm/include/llvm/Metadata.h \ + /usr/home/theraven/llvm/include/llvm/ADT/FoldingSet.h \ + /usr/home/theraven/llvm/include/llvm/ADT/SmallVector.h \ + /usr/home/theraven/llvm/include/llvm/ADT/SmallPtrSet.h \ + /usr/home/theraven/llvm/include/llvm/Support/ErrorHandling.h \ + /usr/home/theraven/llvm/include/llvm/Support/Compiler.h \ + /usr/home/theraven/llvm/include/llvm/Support/ValueHandle.h \ + /usr/home/theraven/llvm/include/llvm/ADT/DenseMapInfo.h \ + /usr/home/theraven/llvm/include/llvm/ADT/PointerIntPair.h \ + /usr/home/theraven/llvm/include/llvm/Value.h \ + /usr/home/theraven/llvm/include/llvm/Function.h \ + /usr/home/theraven/llvm/include/llvm/Instructions.h \ + /usr/home/theraven/llvm/include/llvm/InstrTypes.h \ + /usr/home/theraven/llvm/include/llvm/Operator.h \ + /usr/home/theraven/llvm/include/llvm/Constants.h \ + /usr/home/theraven/llvm/include/llvm/DerivedTypes.h + +/usr/home/theraven/llvm/include/llvm/Constants.h: + +/usr/home/theraven/llvm/include/llvm/Constant.h: + +/usr/home/theraven/llvm/include/llvm/User.h: + +/usr/home/theraven/llvm/include/llvm/Value.h: + +/usr/home/theraven/llvm/include/llvm/AbstractTypeUser.h: + +/usr/home/theraven/llvm/include/llvm/Use.h: + +/usr/home/theraven/llvm/include/llvm/Support/Casting.h: + +/usr/home/theraven/llvm/include/llvm/ADT/PointerIntPair.h: + +/usr/home/theraven/llvm/include/llvm/Support/PointerLikeTypeTraits.h: + +/usr/home/theraven/llvm/include/llvm/Support/DataTypes.h: + +/usr/home/theraven/llvm/include/llvm/ADT/StringRef.h: + +/usr/home/theraven/llvm/include/llvm/ADT/Twine.h: + +/usr/home/theraven/llvm/include/llvm/ADT/StringRef.h: + +/usr/home/theraven/llvm/include/llvm/Support/DataTypes.h: + +/usr/home/theraven/llvm/include/llvm/Type.h: + +/usr/home/theraven/llvm/include/llvm/LLVMContext.h: + +/usr/home/theraven/llvm/include/llvm/Support/DataTypes.h: + +/usr/home/theraven/llvm/include/llvm/System/Atomic.h: + +/usr/home/theraven/llvm/include/llvm/Support/DataTypes.h: + +/usr/home/theraven/llvm/include/llvm/ADT/GraphTraits.h: + +/usr/home/theraven/llvm/include/llvm/OperandTraits.h: + +/usr/home/theraven/llvm/include/llvm/ADT/APInt.h: + +/usr/home/theraven/llvm/include/llvm/Support/MathExtras.h: + +/usr/home/theraven/llvm/include/llvm/ADT/APFloat.h: + +/usr/home/theraven/llvm/include/llvm/ADT/APInt.h: + +/usr/home/theraven/llvm/include/llvm/ADT/SmallVector.h: + +/usr/home/theraven/llvm/include/llvm/Support/type_traits.h: + +/usr/home/theraven/llvm/include/llvm/Pass.h: + +/usr/home/theraven/llvm/include/llvm/PassSupport.h: + +/usr/home/theraven/llvm/include/llvm/PassAnalysisSupport.h: + +/usr/home/theraven/llvm/include/llvm/Module.h: + +/usr/home/theraven/llvm/include/llvm/Function.h: + +/usr/home/theraven/llvm/include/llvm/GlobalValue.h: + +/usr/home/theraven/llvm/include/llvm/CallingConv.h: + +/usr/home/theraven/llvm/include/llvm/BasicBlock.h: + +/usr/home/theraven/llvm/include/llvm/Instruction.h: + +/usr/home/theraven/llvm/include/llvm/ADT/ilist_node.h: + +/usr/home/theraven/llvm/include/llvm/Instruction.def: + +/usr/home/theraven/llvm/include/llvm/SymbolTableListTraits.h: + +/usr/home/theraven/llvm/include/llvm/ADT/ilist.h: + +/usr/home/theraven/llvm/include/llvm/Argument.h: + +/usr/home/theraven/llvm/include/llvm/Attributes.h: + +/usr/home/theraven/llvm/include/llvm/Support/MathExtras.h: + +/usr/home/theraven/llvm/include/llvm/GlobalVariable.h: + +/usr/home/theraven/llvm/include/llvm/GlobalAlias.h: + +/usr/home/theraven/llvm/include/llvm/Metadata.h: + +/usr/home/theraven/llvm/include/llvm/ADT/FoldingSet.h: + +/usr/home/theraven/llvm/include/llvm/ADT/SmallVector.h: + +/usr/home/theraven/llvm/include/llvm/ADT/SmallPtrSet.h: + +/usr/home/theraven/llvm/include/llvm/Support/ErrorHandling.h: + +/usr/home/theraven/llvm/include/llvm/Support/Compiler.h: + +/usr/home/theraven/llvm/include/llvm/Support/ValueHandle.h: + +/usr/home/theraven/llvm/include/llvm/ADT/DenseMapInfo.h: + +/usr/home/theraven/llvm/include/llvm/ADT/PointerIntPair.h: + +/usr/home/theraven/llvm/include/llvm/Value.h: + +/usr/home/theraven/llvm/include/llvm/Function.h: + +/usr/home/theraven/llvm/include/llvm/Instructions.h: + +/usr/home/theraven/llvm/include/llvm/InstrTypes.h: + +/usr/home/theraven/llvm/include/llvm/Operator.h: + +/usr/home/theraven/llvm/include/llvm/Constants.h: + +/usr/home/theraven/llvm/include/llvm/DerivedTypes.h: diff --git a/opts/IvarPass.cpp b/opts/IvarPass.cpp new file mode 100644 index 0000000..f7de826 --- /dev/null +++ b/opts/IvarPass.cpp @@ -0,0 +1,127 @@ +#include "llvm/Pass.h" +#include "llvm/Function.h" +#include "llvm/Module.h" +#include "llvm/Instructions.h" +#include "llvm/GlobalAlias.h" +#include "llvm/GlobalVariable.h" +#include "llvm/Constants.h" +#include + +using namespace llvm; +using std::string; + +namespace +{ + class GNUNonfragileIvarPass : public FunctionPass + { + + public: + static char ID; + GNUNonfragileIvarPass() : FunctionPass((intptr_t)&ID) {} + + Module *M; + size_t PointerSize; + virtual bool doInitialization(Module &Mod) { + M = &Mod; + PointerSize = 8; + if (M->getPointerSize() == Module::Pointer32) + PointerSize = 4; + return false; + } + + std::string getSuperName(Constant *ClsStruct) { + GlobalVariable *name = + cast(ClsStruct->getOperand(1)->getOperand(0)); + return cast(name->getInitializer())->getAsString(); + } + + size_t sizeOfClass(const std::string &className) { + if (className.compare(0, 8, "NSObject") == 0 || + className.compare(0, 6, "Object") == 0) { + return PointerSize; + } + GlobalVariable *Cls = M->getGlobalVariable("_OBJC_CLASS_" + className); + if (!Cls) return 0; + Constant *ClsStruct = Cls->getInitializer(); + // Size is initialized to be negative. + ConstantInt *Size = cast(ClsStruct->getOperand(5)); + return sizeOfClass(getSuperName(ClsStruct)) - Size->getSExtValue(); + } + + size_t hardCodedOffset(const StringRef &className, + const StringRef &ivarName) { + GlobalVariable *Cls = M->getGlobalVariable(("_OBJC_CLASS_" + className).str(), true); + if (!Cls) return 0; + Constant *ClsStruct = Cls->getInitializer(); + size_t superSize = sizeOfClass(getSuperName(ClsStruct)); + if (!superSize) return 0; + ConstantStruct *IvarStruct = cast( + cast(ClsStruct->getOperand(6))->getInitializer()); + int ivarCount = cast(IvarStruct->getOperand(0))->getSExtValue(); + Constant *ivars = IvarStruct->getOperand(1); + for (int i=0 ; igetOperand(i); + GlobalVariable *name = + cast(ivar->getOperand(0)->getOperand(0)); + std::string ivarNameStr = + cast(name->getInitializer())->getAsString(); + if (ivarNameStr.compare(0, ivarName.size(), ivarName.str()) == 0) + return superSize + + cast(ivar->getOperand(2))->getSExtValue(); + } + return 0; + } + + virtual bool runOnFunction(Function &F) { + bool modified = false; + //llvm::cerr << "IvarPass: " << F.getName() << "\n"; + for (Function::iterator i=F.begin(), end=F.end() ; + i != end ; ++i) { + for (BasicBlock::iterator b=i->begin(), last=i->end() ; + b != last ; ++b) { + if (LoadInst *indirectload = dyn_cast(b)) { + if (LoadInst *load = dyn_cast(indirectload->getOperand(0))) { + if (GlobalVariable *ivar = + dyn_cast(load->getOperand(0))) { + StringRef variableName = ivar->getName(); + if (!variableName.startswith("__objc_ivar_offset_")) + break; + size_t prefixLength = strlen("__objc_ivar_offset_"); + + StringRef suffix = variableName.substr(prefixLength, + variableName.size()-prefixLength); + + std::pair parts = suffix.split('.'); + StringRef className = parts.first; + StringRef ivarName = parts.second; + + // If the class, and all superclasses, are visible in this module + // then we can hard-code the ivar offset + if (size_t offset = hardCodedOffset(className, ivarName)) { + indirectload->replaceAllUsesWith(ConstantInt::get(indirectload->getType(), offset)); + modified = true; + } else { + // If the class was compiled with the new + if (Value *offset = + M->getGlobalVariable(("__objc_ivar_offset_value_" + suffix).str())) { + load->replaceAllUsesWith(offset); + modified = true; + } + } + } + } + } + } + } + return modified; + } + }; + + char GNUNonfragileIvarPass::ID = 0; + RegisterPass X("gnu-nonfragile-ivar", "Ivar fragility pass"); +} + +FunctionPass *createGNUNonfragileIvarPass(void) +{ + return new GNUNonfragileIvarPass(); +} diff --git a/opts/Makefile b/opts/Makefile new file mode 100644 index 0000000..cd9dbb3 --- /dev/null +++ b/opts/Makefile @@ -0,0 +1,7 @@ +LEVEL = ../../../ +LIBRARYNAME = GNUObjCRuntime +LOADABLE_MODULE = 1 +USEDLIBS = + +include $(LEVEL)/Makefile.common + diff --git a/opts/README b/opts/README new file mode 100644 index 0000000..9a646ad --- /dev/null +++ b/opts/README @@ -0,0 +1,30 @@ +GNUstep Runtime Optimisations +============================= + +This directory contains LLVM optimisations specific to libobjc2. To build +them, you must copy this directory to llvm/lib/Transforms/GNURuntime (where +llvm is the root of your llvm checkout). + +Running GNU make will then create GNUObjCRuntime.so. This library can be +passed to opt to run optimisations on bitcode generated with clang or +LanguageKit. + +Non-Fragile Ivar Pass +--------------------- + +Running `opt -gnu-nonfragile-ivar` will invoke the non-fragile instance +variable lowering pass. This will turn non-fragile instance variable accesses, +which go via one or two indirection layers, into more fragile ones. If a class +and all of its superclasses are present in the module then this pass will turn +indirect instance variable accesses into hard-coded ones. + +For this pass to be most useful, it should be run as a link-time optimisation. + +Type Feedback +------------- + +Running `opt -gnu-objc-type-feedback` enables type feedback. Objective-C +message lookups will be replaced by calls to the profiling version in the +runtime library. The generated data can then be used for future optimisations +(speculative inlining, polymorphic inline caching, and so on), which have not +yet been written. diff --git a/opts/TypeFeedback.cpp b/opts/TypeFeedback.cpp new file mode 100644 index 0000000..2286536 --- /dev/null +++ b/opts/TypeFeedback.cpp @@ -0,0 +1,87 @@ +#include "llvm/Constants.h" +#include "llvm/Pass.h" +#include "llvm/Module.h" +#include "llvm/Function.h" +#include "llvm/Instructions.h" +#include + +using namespace llvm; + +namespace { + struct GNUObjCTypeFeedback : public ModulePass { + + typedef std::pair callPair; + typedef std::vector replacementVector; + static char ID; + uint32_t callsiteCount; + const IntegerType *Int32Ty; + GNUObjCTypeFeedback() : ModulePass(&ID), callsiteCount(0) {} + + void profileFunction(Function &F, Constant *ModuleID) + { + for (Function::iterator i=F.begin(), e=F.end() ; + i != e ; ++i) + { + replacementVector replacements; + for (BasicBlock::iterator b=i->begin(), last=i->end() ; + b != last ; ++b) + { + Module *M = F.getParent(); + if (CallInst *call = dyn_cast(b)) + { + if (Function *callee = call->getCalledFunction()) + { + if (callee->getName() == "objc_msg_lookup_sender") + { + llvm::Value *args[] = { call->getOperand(1), + call->getOperand(2), call->getOperand(3), + ModuleID, ConstantInt::get(Int32Ty, + callsiteCount++) }; + Function *profile = cast( + M->getOrInsertFunction("objc_msg_lookup_profile", + callee->getFunctionType()->getReturnType(), + args[0]->getType(), args[1]->getType(), + args[2]->getType(), + ModuleID->getType(), Int32Ty, NULL)); + llvm::CallInst *profileCall = + CallInst::Create(profile, args, args+5, "", call); + replacements.push_back(callPair(call, profileCall)); + } + } + } + } + for (replacementVector::iterator r=replacements.begin(), + e=replacements.end() ; e!=r ; r++) + { + r->first->replaceAllUsesWith(r->second); + r->second->getParent()->getInstList().erase(r->first); + } + } + } + + public: + virtual bool runOnModule(Module &M) + { + LLVMContext &VMContext = M.getContext(); + Int32Ty = IntegerType::get(VMContext, 32); + Constant *moduleName = + ConstantArray::get(VMContext, M.getModuleIdentifier(), true); + moduleName = new GlobalVariable(M, moduleName->getType(), true, + GlobalValue::InternalLinkage, moduleName, + ".objc_profile_module_name"); + + for (Module::iterator F=M.begin(), e=M.end() ; + F != e ; ++F) + { + profileFunction(*F, moduleName); + } + return true; + } + + }; + + char GNUObjCTypeFeedback::ID = 0; + RegisterPass X("gnu-objc-type-feedback", + "Objective-C type feedback for the GNU runtime.", false, true); +} +