1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | #ifndef LLVM_CLANG_LIB_CODEGEN_CGVALUE_H |
15 | #define LLVM_CLANG_LIB_CODEGEN_CGVALUE_H |
16 | |
17 | #include "clang/AST/ASTContext.h" |
18 | #include "clang/AST/Type.h" |
19 | #include "llvm/IR/Value.h" |
20 | #include "llvm/IR/Type.h" |
21 | #include "Address.h" |
22 | #include "CodeGenTBAA.h" |
23 | |
24 | namespace llvm { |
25 | class Constant; |
26 | class MDNode; |
27 | } |
28 | |
29 | namespace clang { |
30 | namespace CodeGen { |
31 | class AggValueSlot; |
32 | struct CGBitFieldInfo; |
33 | |
34 | |
35 | |
36 | |
37 | |
38 | class RValue { |
39 | enum Flavor { Scalar, Complex, Aggregate }; |
40 | |
41 | |
42 | |
43 | enum { AggAlignShift = 4 }; |
44 | |
45 | |
46 | llvm::PointerIntPair<llvm::Value *, 2, Flavor> V1; |
47 | |
48 | llvm::PointerIntPair<llvm::Value *, 1, bool> V2; |
49 | |
50 | public: |
51 | bool isScalar() const { return V1.getInt() == Scalar; } |
52 | bool isComplex() const { return V1.getInt() == Complex; } |
53 | bool isAggregate() const { return V1.getInt() == Aggregate; } |
54 | |
55 | bool isVolatileQualified() const { return V2.getInt(); } |
56 | |
57 | |
58 | llvm::Value *getScalarVal() const { |
59 | (0) . __assert_fail ("isScalar() && \"Not a scalar!\"", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/CGValue.h", 59, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(isScalar() && "Not a scalar!"); |
60 | return V1.getPointer(); |
61 | } |
62 | |
63 | |
64 | |
65 | std::pair<llvm::Value *, llvm::Value *> getComplexVal() const { |
66 | return std::make_pair(V1.getPointer(), V2.getPointer()); |
67 | } |
68 | |
69 | |
70 | Address getAggregateAddress() const { |
71 | (0) . __assert_fail ("isAggregate() && \"Not an aggregate!\"", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/CGValue.h", 71, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(isAggregate() && "Not an aggregate!"); |
72 | auto align = reinterpret_cast<uintptr_t>(V2.getPointer()) >> AggAlignShift; |
73 | return Address(V1.getPointer(), CharUnits::fromQuantity(align)); |
74 | } |
75 | llvm::Value *getAggregatePointer() const { |
76 | (0) . __assert_fail ("isAggregate() && \"Not an aggregate!\"", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/CGValue.h", 76, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(isAggregate() && "Not an aggregate!"); |
77 | return V1.getPointer(); |
78 | } |
79 | |
80 | static RValue getIgnored() { |
81 | |
82 | return get(nullptr); |
83 | } |
84 | |
85 | static RValue get(llvm::Value *V) { |
86 | RValue ER; |
87 | ER.V1.setPointer(V); |
88 | ER.V1.setInt(Scalar); |
89 | ER.V2.setInt(false); |
90 | return ER; |
91 | } |
92 | static RValue getComplex(llvm::Value *V1, llvm::Value *V2) { |
93 | RValue ER; |
94 | ER.V1.setPointer(V1); |
95 | ER.V2.setPointer(V2); |
96 | ER.V1.setInt(Complex); |
97 | ER.V2.setInt(false); |
98 | return ER; |
99 | } |
100 | static RValue getComplex(const std::pair<llvm::Value *, llvm::Value *> &C) { |
101 | return getComplex(C.first, C.second); |
102 | } |
103 | |
104 | |
105 | |
106 | static RValue getAggregate(Address addr, bool isVolatile = false) { |
107 | RValue ER; |
108 | ER.V1.setPointer(addr.getPointer()); |
109 | ER.V1.setInt(Aggregate); |
110 | |
111 | auto align = static_cast<uintptr_t>(addr.getAlignment().getQuantity()); |
112 | ER.V2.setPointer(reinterpret_cast<llvm::Value*>(align << AggAlignShift)); |
113 | ER.V2.setInt(isVolatile); |
114 | return ER; |
115 | } |
116 | }; |
117 | |
118 | |
119 | enum ARCPreciseLifetime_t { |
120 | ARCImpreciseLifetime, ARCPreciseLifetime |
121 | }; |
122 | |
123 | |
124 | |
125 | enum class AlignmentSource { |
126 | |
127 | |
128 | |
129 | Decl, |
130 | |
131 | |
132 | |
133 | |
134 | AttributedType, |
135 | |
136 | |
137 | |
138 | Type |
139 | }; |
140 | |
141 | |
142 | |
143 | static inline AlignmentSource getFieldAlignmentSource(AlignmentSource Source) { |
144 | |
145 | |
146 | return AlignmentSource::Decl; |
147 | } |
148 | |
149 | class LValueBaseInfo { |
150 | AlignmentSource AlignSource; |
151 | |
152 | public: |
153 | explicit LValueBaseInfo(AlignmentSource Source = AlignmentSource::Type) |
154 | : AlignSource(Source) {} |
155 | AlignmentSource getAlignmentSource() const { return AlignSource; } |
156 | void setAlignmentSource(AlignmentSource Source) { AlignSource = Source; } |
157 | |
158 | void mergeForCast(const LValueBaseInfo &Info) { |
159 | setAlignmentSource(Info.getAlignmentSource()); |
160 | } |
161 | }; |
162 | |
163 | |
164 | |
165 | |
166 | class LValue { |
167 | enum { |
168 | Simple, |
169 | VectorElt, |
170 | BitField, |
171 | ExtVectorElt, |
172 | GlobalReg |
173 | } LVType; |
174 | |
175 | llvm::Value *V; |
176 | |
177 | union { |
178 | |
179 | llvm::Value *VectorIdx; |
180 | |
181 | |
182 | llvm::Constant *VectorElts; |
183 | |
184 | |
185 | const CGBitFieldInfo *BitFieldInfo; |
186 | }; |
187 | |
188 | QualType Type; |
189 | |
190 | |
191 | Qualifiers Quals; |
192 | |
193 | |
194 | |
195 | unsigned Alignment; |
196 | |
197 | |
198 | bool Ivar:1; |
199 | |
200 | |
201 | bool ObjIsArray:1; |
202 | |
203 | |
204 | |
205 | bool NonGC: 1; |
206 | |
207 | |
208 | bool GlobalObjCRef : 1; |
209 | |
210 | |
211 | bool ThreadLocalRef : 1; |
212 | |
213 | |
214 | |
215 | bool ImpreciseLifetime : 1; |
216 | |
217 | |
218 | |
219 | bool Nontemporal : 1; |
220 | |
221 | LValueBaseInfo BaseInfo; |
222 | TBAAAccessInfo TBAAInfo; |
223 | |
224 | Expr *BaseIvarExp; |
225 | |
226 | private: |
227 | void Initialize(QualType Type, Qualifiers Quals, CharUnits Alignment, |
228 | LValueBaseInfo BaseInfo, TBAAAccessInfo TBAAInfo) { |
229 | (0) . __assert_fail ("(!Alignment.isZero() || Type->isIncompleteType()) && \"initializing l-value with zero alignment!\"", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/CGValue.h", 230, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert((!Alignment.isZero() || Type->isIncompleteType()) && |
230 | (0) . __assert_fail ("(!Alignment.isZero() || Type->isIncompleteType()) && \"initializing l-value with zero alignment!\"", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/CGValue.h", 230, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> "initializing l-value with zero alignment!"); |
231 | this->Type = Type; |
232 | this->Quals = Quals; |
233 | const unsigned MaxAlign = 1U << 31; |
234 | this->Alignment = Alignment.getQuantity() <= MaxAlign |
235 | ? Alignment.getQuantity() |
236 | : MaxAlign; |
237 | (0) . __assert_fail ("this->Alignment == Alignment.getQuantity() && \"Alignment exceeds allowed max!\"", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/CGValue.h", 238, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(this->Alignment == Alignment.getQuantity() && |
238 | (0) . __assert_fail ("this->Alignment == Alignment.getQuantity() && \"Alignment exceeds allowed max!\"", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/CGValue.h", 238, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> "Alignment exceeds allowed max!"); |
239 | this->BaseInfo = BaseInfo; |
240 | this->TBAAInfo = TBAAInfo; |
241 | |
242 | |
243 | this->Ivar = this->ObjIsArray = this->NonGC = this->GlobalObjCRef = false; |
244 | this->ImpreciseLifetime = false; |
245 | this->Nontemporal = false; |
246 | this->ThreadLocalRef = false; |
247 | this->BaseIvarExp = nullptr; |
248 | } |
249 | |
250 | public: |
251 | bool isSimple() const { return LVType == Simple; } |
252 | bool isVectorElt() const { return LVType == VectorElt; } |
253 | bool isBitField() const { return LVType == BitField; } |
254 | bool isExtVectorElt() const { return LVType == ExtVectorElt; } |
255 | bool isGlobalReg() const { return LVType == GlobalReg; } |
256 | |
257 | bool isVolatileQualified() const { return Quals.hasVolatile(); } |
258 | bool isRestrictQualified() const { return Quals.hasRestrict(); } |
259 | unsigned getVRQualifiers() const { |
260 | return Quals.getCVRQualifiers() & ~Qualifiers::Const; |
261 | } |
262 | |
263 | QualType getType() const { return Type; } |
264 | |
265 | Qualifiers::ObjCLifetime getObjCLifetime() const { |
266 | return Quals.getObjCLifetime(); |
267 | } |
268 | |
269 | bool isObjCIvar() const { return Ivar; } |
270 | void setObjCIvar(bool Value) { Ivar = Value; } |
271 | |
272 | bool isObjCArray() const { return ObjIsArray; } |
273 | void setObjCArray(bool Value) { ObjIsArray = Value; } |
274 | |
275 | bool isNonGC () const { return NonGC; } |
276 | void setNonGC(bool Value) { NonGC = Value; } |
277 | |
278 | bool isGlobalObjCRef() const { return GlobalObjCRef; } |
279 | void setGlobalObjCRef(bool Value) { GlobalObjCRef = Value; } |
280 | |
281 | bool isThreadLocalRef() const { return ThreadLocalRef; } |
282 | void setThreadLocalRef(bool Value) { ThreadLocalRef = Value;} |
283 | |
284 | ARCPreciseLifetime_t isARCPreciseLifetime() const { |
285 | return ARCPreciseLifetime_t(!ImpreciseLifetime); |
286 | } |
287 | void setARCPreciseLifetime(ARCPreciseLifetime_t value) { |
288 | ImpreciseLifetime = (value == ARCImpreciseLifetime); |
289 | } |
290 | bool isNontemporal() const { return Nontemporal; } |
291 | void setNontemporal(bool Value) { Nontemporal = Value; } |
292 | |
293 | bool isObjCWeak() const { |
294 | return Quals.getObjCGCAttr() == Qualifiers::Weak; |
295 | } |
296 | bool isObjCStrong() const { |
297 | return Quals.getObjCGCAttr() == Qualifiers::Strong; |
298 | } |
299 | |
300 | bool isVolatile() const { |
301 | return Quals.hasVolatile(); |
302 | } |
303 | |
304 | Expr *getBaseIvarExp() const { return BaseIvarExp; } |
305 | void setBaseIvarExp(Expr *V) { BaseIvarExp = V; } |
306 | |
307 | TBAAAccessInfo getTBAAInfo() const { return TBAAInfo; } |
308 | void setTBAAInfo(TBAAAccessInfo Info) { TBAAInfo = Info; } |
309 | |
310 | const Qualifiers &getQuals() const { return Quals; } |
311 | Qualifiers &getQuals() { return Quals; } |
312 | |
313 | LangAS getAddressSpace() const { return Quals.getAddressSpace(); } |
314 | |
315 | CharUnits getAlignment() const { return CharUnits::fromQuantity(Alignment); } |
316 | void setAlignment(CharUnits A) { Alignment = A.getQuantity(); } |
317 | |
318 | LValueBaseInfo getBaseInfo() const { return BaseInfo; } |
319 | void setBaseInfo(LValueBaseInfo Info) { BaseInfo = Info; } |
320 | |
321 | |
322 | llvm::Value *getPointer() const { |
323 | assert(isSimple()); |
324 | return V; |
325 | } |
326 | Address getAddress() const { return Address(getPointer(), getAlignment()); } |
327 | void setAddress(Address address) { |
328 | assert(isSimple()); |
329 | V = address.getPointer(); |
330 | Alignment = address.getAlignment().getQuantity(); |
331 | } |
332 | |
333 | |
334 | Address getVectorAddress() const { |
335 | return Address(getVectorPointer(), getAlignment()); |
336 | } |
337 | llvm::Value *getVectorPointer() const { assert(isVectorElt()); return V; } |
338 | llvm::Value *getVectorIdx() const { assert(isVectorElt()); return VectorIdx; } |
339 | |
340 | |
341 | Address getExtVectorAddress() const { |
342 | return Address(getExtVectorPointer(), getAlignment()); |
343 | } |
344 | llvm::Value *getExtVectorPointer() const { |
345 | assert(isExtVectorElt()); |
346 | return V; |
347 | } |
348 | llvm::Constant *getExtVectorElts() const { |
349 | assert(isExtVectorElt()); |
350 | return VectorElts; |
351 | } |
352 | |
353 | |
354 | Address getBitFieldAddress() const { |
355 | return Address(getBitFieldPointer(), getAlignment()); |
356 | } |
357 | llvm::Value *getBitFieldPointer() const { assert(isBitField()); return V; } |
358 | const CGBitFieldInfo &getBitFieldInfo() const { |
359 | assert(isBitField()); |
360 | return *BitFieldInfo; |
361 | } |
362 | |
363 | |
364 | llvm::Value *getGlobalReg() const { assert(isGlobalReg()); return V; } |
365 | |
366 | static LValue MakeAddr(Address address, QualType type, ASTContext &Context, |
367 | LValueBaseInfo BaseInfo, TBAAAccessInfo TBAAInfo) { |
368 | Qualifiers qs = type.getQualifiers(); |
369 | qs.setObjCGCAttr(Context.getObjCGCAttrKind(type)); |
370 | |
371 | LValue R; |
372 | R.LVType = Simple; |
373 | getType()->isPointerTy()", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/CGValue.h", 373, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(address.getPointer()->getType()->isPointerTy()); |
374 | R.V = address.getPointer(); |
375 | R.Initialize(type, qs, address.getAlignment(), BaseInfo, TBAAInfo); |
376 | return R; |
377 | } |
378 | |
379 | static LValue MakeVectorElt(Address vecAddress, llvm::Value *Idx, |
380 | QualType type, LValueBaseInfo BaseInfo, |
381 | TBAAAccessInfo TBAAInfo) { |
382 | LValue R; |
383 | R.LVType = VectorElt; |
384 | R.V = vecAddress.getPointer(); |
385 | R.VectorIdx = Idx; |
386 | R.Initialize(type, type.getQualifiers(), vecAddress.getAlignment(), |
387 | BaseInfo, TBAAInfo); |
388 | return R; |
389 | } |
390 | |
391 | static LValue MakeExtVectorElt(Address vecAddress, llvm::Constant *Elts, |
392 | QualType type, LValueBaseInfo BaseInfo, |
393 | TBAAAccessInfo TBAAInfo) { |
394 | LValue R; |
395 | R.LVType = ExtVectorElt; |
396 | R.V = vecAddress.getPointer(); |
397 | R.VectorElts = Elts; |
398 | R.Initialize(type, type.getQualifiers(), vecAddress.getAlignment(), |
399 | BaseInfo, TBAAInfo); |
400 | return R; |
401 | } |
402 | |
403 | |
404 | |
405 | |
406 | |
407 | |
408 | |
409 | static LValue MakeBitfield(Address Addr, const CGBitFieldInfo &Info, |
410 | QualType type, LValueBaseInfo BaseInfo, |
411 | TBAAAccessInfo TBAAInfo) { |
412 | LValue R; |
413 | R.LVType = BitField; |
414 | R.V = Addr.getPointer(); |
415 | R.BitFieldInfo = &Info; |
416 | R.Initialize(type, type.getQualifiers(), Addr.getAlignment(), BaseInfo, |
417 | TBAAInfo); |
418 | return R; |
419 | } |
420 | |
421 | static LValue MakeGlobalReg(Address Reg, QualType type) { |
422 | LValue R; |
423 | R.LVType = GlobalReg; |
424 | R.V = Reg.getPointer(); |
425 | R.Initialize(type, type.getQualifiers(), Reg.getAlignment(), |
426 | LValueBaseInfo(AlignmentSource::Decl), TBAAAccessInfo()); |
427 | return R; |
428 | } |
429 | |
430 | RValue asAggregateRValue() const { |
431 | return RValue::getAggregate(getAddress(), isVolatileQualified()); |
432 | } |
433 | }; |
434 | |
435 | |
436 | class AggValueSlot { |
437 | |
438 | llvm::Value *Addr; |
439 | |
440 | |
441 | Qualifiers Quals; |
442 | |
443 | unsigned Alignment; |
444 | |
445 | |
446 | |
447 | |
448 | bool DestructedFlag : 1; |
449 | |
450 | |
451 | |
452 | |
453 | bool ObjCGCFlag : 1; |
454 | |
455 | |
456 | |
457 | |
458 | bool ZeroedFlag : 1; |
459 | |
460 | |
461 | |
462 | |
463 | |
464 | |
465 | |
466 | |
467 | |
468 | |
469 | |
470 | |
471 | |
472 | bool AliasedFlag : 1; |
473 | |
474 | |
475 | |
476 | |
477 | |
478 | |
479 | bool OverlapFlag : 1; |
480 | |
481 | |
482 | |
483 | |
484 | |
485 | |
486 | bool SanitizerCheckedFlag : 1; |
487 | |
488 | public: |
489 | enum IsAliased_t { IsNotAliased, IsAliased }; |
490 | enum IsDestructed_t { IsNotDestructed, IsDestructed }; |
491 | enum IsZeroed_t { IsNotZeroed, IsZeroed }; |
492 | enum Overlap_t { DoesNotOverlap, MayOverlap }; |
493 | enum NeedsGCBarriers_t { DoesNotNeedGCBarriers, NeedsGCBarriers }; |
494 | enum IsSanitizerChecked_t { IsNotSanitizerChecked, IsSanitizerChecked }; |
495 | |
496 | |
497 | |
498 | static AggValueSlot ignored() { |
499 | return forAddr(Address::invalid(), Qualifiers(), IsNotDestructed, |
500 | DoesNotNeedGCBarriers, IsNotAliased, DoesNotOverlap); |
501 | } |
502 | |
503 | |
504 | |
505 | |
506 | |
507 | |
508 | |
509 | |
510 | |
511 | |
512 | |
513 | static AggValueSlot forAddr(Address addr, |
514 | Qualifiers quals, |
515 | IsDestructed_t isDestructed, |
516 | NeedsGCBarriers_t needsGC, |
517 | IsAliased_t isAliased, |
518 | Overlap_t mayOverlap, |
519 | IsZeroed_t isZeroed = IsNotZeroed, |
520 | IsSanitizerChecked_t isChecked = IsNotSanitizerChecked) { |
521 | AggValueSlot AV; |
522 | if (addr.isValid()) { |
523 | AV.Addr = addr.getPointer(); |
524 | AV.Alignment = addr.getAlignment().getQuantity(); |
525 | } else { |
526 | AV.Addr = nullptr; |
527 | AV.Alignment = 0; |
528 | } |
529 | AV.Quals = quals; |
530 | AV.DestructedFlag = isDestructed; |
531 | AV.ObjCGCFlag = needsGC; |
532 | AV.ZeroedFlag = isZeroed; |
533 | AV.AliasedFlag = isAliased; |
534 | AV.OverlapFlag = mayOverlap; |
535 | AV.SanitizerCheckedFlag = isChecked; |
536 | return AV; |
537 | } |
538 | |
539 | static AggValueSlot forLValue(const LValue &LV, |
540 | IsDestructed_t isDestructed, |
541 | NeedsGCBarriers_t needsGC, |
542 | IsAliased_t isAliased, |
543 | Overlap_t mayOverlap, |
544 | IsZeroed_t isZeroed = IsNotZeroed, |
545 | IsSanitizerChecked_t isChecked = IsNotSanitizerChecked) { |
546 | return forAddr(LV.getAddress(), LV.getQuals(), isDestructed, needsGC, |
547 | isAliased, mayOverlap, isZeroed, isChecked); |
548 | } |
549 | |
550 | IsDestructed_t isExternallyDestructed() const { |
551 | return IsDestructed_t(DestructedFlag); |
552 | } |
553 | void setExternallyDestructed(bool destructed = true) { |
554 | DestructedFlag = destructed; |
555 | } |
556 | |
557 | Qualifiers getQualifiers() const { return Quals; } |
558 | |
559 | bool isVolatile() const { |
560 | return Quals.hasVolatile(); |
561 | } |
562 | |
563 | void setVolatile(bool flag) { |
564 | if (flag) |
565 | Quals.addVolatile(); |
566 | else |
567 | Quals.removeVolatile(); |
568 | } |
569 | |
570 | Qualifiers::ObjCLifetime getObjCLifetime() const { |
571 | return Quals.getObjCLifetime(); |
572 | } |
573 | |
574 | NeedsGCBarriers_t requiresGCollection() const { |
575 | return NeedsGCBarriers_t(ObjCGCFlag); |
576 | } |
577 | |
578 | llvm::Value *getPointer() const { |
579 | return Addr; |
580 | } |
581 | |
582 | Address getAddress() const { |
583 | return Address(Addr, getAlignment()); |
584 | } |
585 | |
586 | bool isIgnored() const { |
587 | return Addr == nullptr; |
588 | } |
589 | |
590 | CharUnits getAlignment() const { |
591 | return CharUnits::fromQuantity(Alignment); |
592 | } |
593 | |
594 | IsAliased_t isPotentiallyAliased() const { |
595 | return IsAliased_t(AliasedFlag); |
596 | } |
597 | |
598 | Overlap_t mayOverlap() const { |
599 | return Overlap_t(OverlapFlag); |
600 | } |
601 | |
602 | bool isSanitizerChecked() const { |
603 | return SanitizerCheckedFlag; |
604 | } |
605 | |
606 | RValue asRValue() const { |
607 | if (isIgnored()) { |
608 | return RValue::getIgnored(); |
609 | } else { |
610 | return RValue::getAggregate(getAddress(), isVolatile()); |
611 | } |
612 | } |
613 | |
614 | void setZeroed(bool V = true) { ZeroedFlag = V; } |
615 | IsZeroed_t isZeroed() const { |
616 | return IsZeroed_t(ZeroedFlag); |
617 | } |
618 | |
619 | |
620 | |
621 | |
622 | CharUnits getPreferredSize(ASTContext &Ctx, QualType Type) const { |
623 | return mayOverlap() ? Ctx.getTypeInfoDataSizeInChars(Type).first |
624 | : Ctx.getTypeSizeInChars(Type); |
625 | } |
626 | }; |
627 | |
628 | } |
629 | } |
630 | |
631 | #endif |
632 | |