1 //===- GlobalSplit.cpp - global variable splitter -------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This pass uses inrange annotations on GEP indices to split globals where 10 // beneficial. Clang currently attaches these annotations to references to 11 // virtual table globals under the Itanium ABI for the benefit of the 12 // whole-program virtual call optimization and control flow integrity passes. 13 // 14 //===----------------------------------------------------------------------===// 15 16 #include "llvm/Transforms/IPO/GlobalSplit.h" 17 #include "llvm/ADT/SmallVector.h" 18 #include "llvm/ADT/StringExtras.h" 19 #include "llvm/IR/Constant.h" 20 #include "llvm/IR/Constants.h" 21 #include "llvm/IR/DataLayout.h" 22 #include "llvm/IR/Function.h" 23 #include "llvm/IR/GlobalValue.h" 24 #include "llvm/IR/GlobalVariable.h" 25 #include "llvm/IR/Intrinsics.h" 26 #include "llvm/IR/LLVMContext.h" 27 #include "llvm/IR/Metadata.h" 28 #include "llvm/IR/Module.h" 29 #include "llvm/IR/Operator.h" 30 #include "llvm/IR/Type.h" 31 #include "llvm/IR/User.h" 32 #include "llvm/Pass.h" 33 #include "llvm/Support/Casting.h" 34 #include "llvm/Transforms/IPO.h" 35 #include <cstdint> 36 #include <vector> 37 38 using namespace llvm; 39 40 static bool splitGlobal(GlobalVariable &GV) { 41 // If the address of the global is taken outside of the module, we cannot 42 // apply this transformation. 43 if (!GV.hasLocalLinkage()) 44 return false; 45 46 // We currently only know how to split ConstantStructs. 47 auto *Init = dyn_cast_or_null<ConstantStruct>(GV.getInitializer()); 48 if (!Init) 49 return false; 50 51 // Verify that each user of the global is an inrange getelementptr constant. 52 // From this it follows that any loads from or stores to that global must use 53 // a pointer derived from an inrange getelementptr constant, which is 54 // sufficient to allow us to apply the splitting transform. 55 for (User *U : GV.users()) { 56 if (!isa<Constant>(U)) 57 return false; 58 59 auto *GEP = dyn_cast<GEPOperator>(U); 60 if (!GEP || !GEP->getInRangeIndex() || *GEP->getInRangeIndex() != 1 || 61 !isa<ConstantInt>(GEP->getOperand(1)) || 62 !cast<ConstantInt>(GEP->getOperand(1))->isZero() || 63 !isa<ConstantInt>(GEP->getOperand(2))) 64 return false; 65 } 66 67 SmallVector<MDNode *, 2> Types; 68 GV.getMetadata(LLVMContext::MD_type, Types); 69 70 const DataLayout &DL = GV.getParent()->getDataLayout(); 71 const StructLayout *SL = DL.getStructLayout(Init->getType()); 72 73 IntegerType *Int32Ty = Type::getInt32Ty(GV.getContext()); 74 75 std::vector<GlobalVariable *> SplitGlobals(Init->getNumOperands()); 76 for (unsigned I = 0; I != Init->getNumOperands(); ++I) { 77 // Build a global representing this split piece. 78 auto *SplitGV = 79 new GlobalVariable(*GV.getParent(), Init->getOperand(I)->getType(), 80 GV.isConstant(), GlobalValue::PrivateLinkage, 81 Init->getOperand(I), GV.getName() + "." + utostr(I)); 82 SplitGlobals[I] = SplitGV; 83 84 unsigned SplitBegin = SL->getElementOffset(I); 85 unsigned SplitEnd = (I == Init->getNumOperands() - 1) 86 ? SL->getSizeInBytes() 87 : SL->getElementOffset(I + 1); 88 89 // Rebuild type metadata, adjusting by the split offset. 90 // FIXME: See if we can use DW_OP_piece to preserve debug metadata here. 91 for (MDNode *Type : Types) { 92 uint64_t ByteOffset = cast<ConstantInt>( 93 cast<ConstantAsMetadata>(Type->getOperand(0))->getValue()) 94 ->getZExtValue(); 95 // Type metadata may be attached one byte after the end of the vtable, for 96 // classes without virtual methods in Itanium ABI. AFAIK, it is never 97 // attached to the first byte of a vtable. Subtract one to get the right 98 // slice. 99 // This is making an assumption that vtable groups are the only kinds of 100 // global variables that !type metadata can be attached to, and that they 101 // are either Itanium ABI vtable groups or contain a single vtable (i.e. 102 // Microsoft ABI vtables). 103 uint64_t AttachedTo = (ByteOffset == 0) ? ByteOffset : ByteOffset - 1; 104 if (AttachedTo < SplitBegin || AttachedTo >= SplitEnd) 105 continue; 106 SplitGV->addMetadata( 107 LLVMContext::MD_type, 108 *MDNode::get(GV.getContext(), 109 {ConstantAsMetadata::get( 110 ConstantInt::get(Int32Ty, ByteOffset - SplitBegin)), 111 Type->getOperand(1)})); 112 } 113 } 114 115 for (User *U : GV.users()) { 116 auto *GEP = cast<GEPOperator>(U); 117 unsigned I = cast<ConstantInt>(GEP->getOperand(2))->getZExtValue(); 118 if (I >= SplitGlobals.size()) 119 continue; 120 121 SmallVector<Value *, 4> Ops; 122 Ops.push_back(ConstantInt::get(Int32Ty, 0)); 123 for (unsigned I = 3; I != GEP->getNumOperands(); ++I) 124 Ops.push_back(GEP->getOperand(I)); 125 126 auto *NewGEP = ConstantExpr::getGetElementPtr( 127 SplitGlobals[I]->getInitializer()->getType(), SplitGlobals[I], Ops, 128 GEP->isInBounds()); 129 GEP->replaceAllUsesWith(NewGEP); 130 } 131 132 // Finally, remove the original global. Any remaining uses refer to invalid 133 // elements of the global, so replace with undef. 134 if (!GV.use_empty()) 135 GV.replaceAllUsesWith(UndefValue::get(GV.getType())); 136 GV.eraseFromParent(); 137 return true; 138 } 139 140 static bool splitGlobals(Module &M) { 141 // First, see if the module uses either of the llvm.type.test or 142 // llvm.type.checked.load intrinsics, which indicates that splitting globals 143 // may be beneficial. 144 Function *TypeTestFunc = 145 M.getFunction(Intrinsic::getName(Intrinsic::type_test)); 146 Function *TypeCheckedLoadFunc = 147 M.getFunction(Intrinsic::getName(Intrinsic::type_checked_load)); 148 if ((!TypeTestFunc || TypeTestFunc->use_empty()) && 149 (!TypeCheckedLoadFunc || TypeCheckedLoadFunc->use_empty())) 150 return false; 151 152 bool Changed = false; 153 for (auto I = M.global_begin(); I != M.global_end();) { 154 GlobalVariable &GV = *I; 155 ++I; 156 Changed |= splitGlobal(GV); 157 } 158 return Changed; 159 } 160 161 namespace { 162 163 struct GlobalSplit : public ModulePass { 164 static char ID; 165 166 GlobalSplit() : ModulePass(ID) { 167 initializeGlobalSplitPass(*PassRegistry::getPassRegistry()); 168 } 169 170 bool runOnModule(Module &M) override { 171 if (skipModule(M)) 172 return false; 173 174 return splitGlobals(M); 175 } 176 }; 177 178 } // end anonymous namespace 179 180 char GlobalSplit::ID = 0; 181 182 INITIALIZE_PASS(GlobalSplit, "globalsplit", "Global splitter", false, false) 183 184 ModulePass *llvm::createGlobalSplitPass() { 185 return new GlobalSplit; 186 } 187 188 PreservedAnalyses GlobalSplitPass::run(Module &M, ModuleAnalysisManager &AM) { 189 if (!splitGlobals(M)) 190 return PreservedAnalyses::all(); 191 return PreservedAnalyses::none(); 192 } 193