Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(356)

Side by Side Diff: lib/Transforms/NaCl/StripAttributes.cpp

Issue 939073008: Rebased PNaCl localmods in LLVM to 223109 (Closed)
Patch Set: undo localmod Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « lib/Transforms/NaCl/SimplifyAllocas.cpp ('k') | lib/Transforms/NaCl/StripMetadata.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(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 }
OLDNEW
« no previous file with comments | « lib/Transforms/NaCl/SimplifyAllocas.cpp ('k') | lib/Transforms/NaCl/StripMetadata.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698