OLD | NEW |
(Empty) | |
| 1 //===- StripAttributes.cpp - Remove attributes not supported by PNaCl------===// |
| 2 // |
| 3 // The LLVM Compiler Infrastructure |
| 4 // |
| 5 // This file is distributed under the University of Illinois Open Source |
| 6 // License. See LICENSE.TXT for details. |
| 7 // |
| 8 //===----------------------------------------------------------------------===// |
| 9 // |
| 10 // This pass strips out attributes that are not supported by PNaCl's |
| 11 // stable ABI. Currently, this strips out: |
| 12 // |
| 13 // * Function and argument attributes from functions and function |
| 14 // calls. |
| 15 // * Calling conventions from functions and function calls. |
| 16 // * The "align" attribute on functions. |
| 17 // * The alignment argument of memcpy/memmove/memset intrinsic calls. |
| 18 // * The "unnamed_addr" attribute on functions and global variables. |
| 19 // * The distinction between "internal" and "private" linkage. |
| 20 // * "protected" and "internal" visibility of functions and globals. |
| 21 // * All sections are stripped. A few sections cause warnings. |
| 22 // * The arithmetic attributes "nsw", "nuw" and "exact". |
| 23 // * It reduces the set of possible "align" attributes on memory |
| 24 // accesses. |
| 25 // |
| 26 //===----------------------------------------------------------------------===// |
| 27 |
| 28 #include "llvm/IR/DataLayout.h" |
| 29 #include "llvm/IR/Function.h" |
| 30 #include "llvm/IR/IntrinsicInst.h" |
| 31 #include "llvm/IR/Module.h" |
| 32 #include "llvm/IR/Operator.h" |
| 33 #include "llvm/Pass.h" |
| 34 #include "llvm/IR/CallSite.h" |
| 35 #include "llvm/Transforms/NaCl.h" |
| 36 #include "llvm/Support/raw_ostream.h" |
| 37 |
| 38 using namespace llvm; |
| 39 |
| 40 namespace { |
| 41 // This is a ModulePass so that it can modify attributes of global |
| 42 // variables. |
| 43 class StripAttributes : public ModulePass { |
| 44 public: |
| 45 static char ID; // Pass identification, replacement for typeid |
| 46 StripAttributes() : ModulePass(ID) { |
| 47 initializeStripAttributesPass(*PassRegistry::getPassRegistry()); |
| 48 } |
| 49 |
| 50 virtual bool runOnModule(Module &M); |
| 51 }; |
| 52 } |
| 53 |
| 54 char StripAttributes::ID = 0; |
| 55 INITIALIZE_PASS(StripAttributes, "nacl-strip-attributes", |
| 56 "Strip out attributes that are not part of PNaCl's ABI", |
| 57 false, false) |
| 58 |
| 59 static void CheckAttributes(AttributeSet Attrs) { |
| 60 for (unsigned Slot = 0; Slot < Attrs.getNumSlots(); ++Slot) { |
| 61 for (AttributeSet::iterator Attr = Attrs.begin(Slot), E = Attrs.end(Slot); |
| 62 Attr != E; ++Attr) { |
| 63 if (!Attr->isEnumAttribute()) { |
| 64 continue; |
| 65 } |
| 66 switch (Attr->getKindAsEnum()) { |
| 67 // The vast majority of attributes are hints that can safely |
| 68 // be removed, so don't complain if we see attributes we don't |
| 69 // recognize. |
| 70 default: |
| 71 |
| 72 // The following attributes can affect calling conventions. |
| 73 // Rather than complaining, we just strip these out. |
| 74 // ExpandSmallArguments should have rendered SExt/ZExt |
| 75 // meaningless since the function arguments will be at least |
| 76 // 32-bit. |
| 77 case Attribute::InReg: |
| 78 case Attribute::SExt: |
| 79 case Attribute::ZExt: |
| 80 // These attributes influence ABI decisions that should not be |
| 81 // visible to PNaCl pexes. |
| 82 case Attribute::NonLazyBind: // Only relevant to dynamic linking. |
| 83 case Attribute::NoRedZone: |
| 84 case Attribute::StackAlignment: |
| 85 |
| 86 // The following attributes are just hints, which can be |
| 87 // safely removed. |
| 88 case Attribute::AlwaysInline: |
| 89 case Attribute::InlineHint: |
| 90 case Attribute::MinSize: |
| 91 case Attribute::NoAlias: |
| 92 case Attribute::NoBuiltin: |
| 93 case Attribute::NoCapture: |
| 94 case Attribute::NoDuplicate: |
| 95 case Attribute::NoImplicitFloat: |
| 96 case Attribute::NoInline: |
| 97 case Attribute::NoReturn: |
| 98 case Attribute::OptimizeForSize: |
| 99 case Attribute::ReadNone: |
| 100 case Attribute::ReadOnly: |
| 101 |
| 102 // PNaCl does not support -fstack-protector in the translator. |
| 103 case Attribute::StackProtect: |
| 104 case Attribute::StackProtectReq: |
| 105 case Attribute::StackProtectStrong: |
| 106 // PNaCl does not support ASan in the translator. |
| 107 case Attribute::SanitizeAddress: |
| 108 case Attribute::SanitizeThread: |
| 109 case Attribute::SanitizeMemory: |
| 110 |
| 111 // The Language References cites setjmp() as an example of a |
| 112 // function which returns twice, and says ReturnsTwice is |
| 113 // necessary to disable optimizations such as tail calls. |
| 114 // However, in the PNaCl ABI, setjmp() is an intrinsic, and |
| 115 // user-defined functions are not allowed to return twice. |
| 116 case Attribute::ReturnsTwice: |
| 117 |
| 118 // NoUnwind is not a hint if it causes unwind info to be |
| 119 // omitted, since this will prevent C++ exceptions from |
| 120 // propagating. In the future, when PNaCl supports zero-cost |
| 121 // C++ exception handling using unwind info, we might allow |
| 122 // NoUnwind and UWTable. Alternatively, we might continue to |
| 123 // disallow them, and just generate unwind info for all |
| 124 // functions. |
| 125 case Attribute::NoUnwind: |
| 126 case Attribute::UWTable: |
| 127 break; |
| 128 |
| 129 // A few attributes can change program behaviour if removed, |
| 130 // so check for these. |
| 131 case Attribute::ByVal: |
| 132 case Attribute::StructRet: |
| 133 case Attribute::Alignment: |
| 134 Attrs.dump(); |
| 135 report_fatal_error( |
| 136 "Attribute should already have been removed by ExpandByVal"); |
| 137 |
| 138 case Attribute::Naked: |
| 139 case Attribute::Nest: |
| 140 Attrs.dump(); |
| 141 report_fatal_error("Unsupported attribute"); |
| 142 } |
| 143 } |
| 144 } |
| 145 } |
| 146 |
| 147 static const char* ShouldWarnAboutSection(const char* Section) { |
| 148 static const char* SpecialSections[] = { |
| 149 ".init_array", |
| 150 ".init", |
| 151 ".fini_array", |
| 152 ".fini", |
| 153 |
| 154 // Java/LSB: |
| 155 ".jcr", |
| 156 |
| 157 // LSB: |
| 158 ".ctors", |
| 159 ".dtors", |
| 160 }; |
| 161 |
| 162 for (auto CheckSection : SpecialSections) { |
| 163 if (strcmp(Section, CheckSection) == 0) { |
| 164 return CheckSection; |
| 165 } |
| 166 } |
| 167 |
| 168 return nullptr; |
| 169 } |
| 170 |
| 171 void stripGlobalValueAttrs(GlobalValue *GV) { |
| 172 // In case source code uses __attribute__((visibility("hidden"))) or |
| 173 // __attribute__((visibility("protected"))), strip these attributes. |
| 174 GV->setVisibility(GlobalValue::DefaultVisibility); |
| 175 |
| 176 GV->setUnnamedAddr(false); |
| 177 |
| 178 if (GV->hasSection()) { |
| 179 const char *Section = GV->getSection(); |
| 180 // check for a few special cases |
| 181 if (const char *WarnSection = ShouldWarnAboutSection(Section)) { |
| 182 errs() << "Warning: " << GV->getName() << |
| 183 " will have its section (" << |
| 184 WarnSection << ") stripped.\n"; |
| 185 } |
| 186 |
| 187 if(GlobalObject* GO = dyn_cast<GlobalObject>(GV)) { |
| 188 GO->setSection(""); |
| 189 } |
| 190 // Nothing we can do if GV isn't a GlobalObject. |
| 191 } |
| 192 |
| 193 // Convert "private" linkage to "internal" to reduce the number of |
| 194 // linkage types that need to be represented in PNaCl's wire format. |
| 195 // |
| 196 // We convert "private" to "internal" rather than vice versa because |
| 197 // "private" symbols are omitted from the nexe's symbol table, which |
| 198 // would get in the way of debugging when an unstripped pexe is |
| 199 // translated offline. |
| 200 if (GV->getLinkage() == GlobalValue::PrivateLinkage) |
| 201 GV->setLinkage(GlobalValue::InternalLinkage); |
| 202 } |
| 203 |
| 204 static unsigned normalizeAlignment(DataLayout *DL, unsigned Alignment, |
| 205 Type *Ty, bool IsAtomic) { |
| 206 unsigned MaxAllowed = 1; |
| 207 if (isa<VectorType>(Ty)) |
| 208 // Already handled properly by FixVectorLoadStoreAlignment. |
| 209 return Alignment; |
| 210 if (Ty->isDoubleTy() || Ty->isFloatTy() || IsAtomic) |
| 211 MaxAllowed = DL->getTypeAllocSize(Ty); |
| 212 // If the alignment is set to 0, this means "use the default |
| 213 // alignment for the target", which we fill in explicitly. |
| 214 if (Alignment == 0 || Alignment >= MaxAllowed) |
| 215 return MaxAllowed; |
| 216 return 1; |
| 217 } |
| 218 |
| 219 void stripFunctionAttrs(DataLayout *DL, Function *Func) { |
| 220 CheckAttributes(Func->getAttributes()); |
| 221 Func->setAttributes(AttributeSet()); |
| 222 Func->setCallingConv(CallingConv::C); |
| 223 Func->setAlignment(0); |
| 224 |
| 225 for (Function::iterator BB = Func->begin(), E = Func->end(); |
| 226 BB != E; ++BB) { |
| 227 for (BasicBlock::iterator Inst = BB->begin(), E = BB->end(); |
| 228 Inst != E; ++Inst) { |
| 229 CallSite Call(Inst); |
| 230 if (Call) { |
| 231 CheckAttributes(Call.getAttributes()); |
| 232 Call.setAttributes(AttributeSet()); |
| 233 Call.setCallingConv(CallingConv::C); |
| 234 |
| 235 // Set memcpy(), memmove() and memset() to use pessimistic |
| 236 // alignment assumptions. |
| 237 if (MemIntrinsic *MemOp = dyn_cast<MemIntrinsic>(Inst)) { |
| 238 Type *AlignTy = MemOp->getAlignmentCst()->getType(); |
| 239 MemOp->setAlignment(ConstantInt::get(AlignTy, 1)); |
| 240 } |
| 241 } else if (OverflowingBinaryOperator *Op = |
| 242 dyn_cast<OverflowingBinaryOperator>(Inst)) { |
| 243 cast<BinaryOperator>(Op)->setHasNoUnsignedWrap(false); |
| 244 cast<BinaryOperator>(Op)->setHasNoSignedWrap(false); |
| 245 } else if (PossiblyExactOperator *Op = |
| 246 dyn_cast<PossiblyExactOperator>(Inst)) { |
| 247 cast<BinaryOperator>(Op)->setIsExact(false); |
| 248 } else if (LoadInst *Load = dyn_cast<LoadInst>(Inst)) { |
| 249 Load->setAlignment(normalizeAlignment( |
| 250 DL, Load->getAlignment(), |
| 251 Load->getType(), |
| 252 Load->isAtomic())); |
| 253 } else if (StoreInst *Store = dyn_cast<StoreInst>(Inst)) { |
| 254 Store->setAlignment(normalizeAlignment( |
| 255 DL, Store->getAlignment(), |
| 256 Store->getValueOperand()->getType(), |
| 257 Store->isAtomic())); |
| 258 } |
| 259 } |
| 260 } |
| 261 } |
| 262 |
| 263 bool StripAttributes::runOnModule(Module &M) { |
| 264 DataLayout DL(&M); |
| 265 for (Module::iterator Func = M.begin(), E = M.end(); Func != E; ++Func) { |
| 266 // Avoid stripping attributes from intrinsics because the |
| 267 // constructor for Functions just adds them back again. It would |
| 268 // be confusing if the attributes were sometimes present on |
| 269 // intrinsics and sometimes not. |
| 270 if (!Func->isIntrinsic()) { |
| 271 stripGlobalValueAttrs(Func); |
| 272 stripFunctionAttrs(&DL, Func); |
| 273 } |
| 274 } |
| 275 for (Module::global_iterator GV = M.global_begin(), E = M.global_end(); |
| 276 GV != E; ++GV) { |
| 277 stripGlobalValueAttrs(GV); |
| 278 } |
| 279 return true; |
| 280 } |
| 281 |
| 282 ModulePass *llvm::createStripAttributesPass() { |
| 283 return new StripAttributes(); |
| 284 } |
OLD | NEW |