 |
|
 |
|
| Files: |
1 |
|
Branches Taken: |
70.2% |
217 / 309 |
| Generated: |
2010-02-10 01:31 |
|
Branches Executed: |
93.5% |
289 / 309 |
| |
|
Line Coverage: |
85.2% |
413 / 485 |
| |
 |
|
 |
1 : //===--- CGExprConstant.cpp - Emit LLVM Code from Constant Expressions ----===//
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 contains code to emit Constant Expr nodes as LLVM code.
11 : //
12 : //===----------------------------------------------------------------------===//
13 :
14 : #include "CodeGenFunction.h"
15 : #include "CodeGenModule.h"
16 : #include "CGObjCRuntime.h"
17 : #include "clang/AST/APValue.h"
18 : #include "clang/AST/ASTContext.h"
19 : #include "clang/AST/RecordLayout.h"
20 : #include "clang/AST/StmtVisitor.h"
21 : #include "clang/Basic/Builtins.h"
22 : #include "llvm/Constants.h"
23 : #include "llvm/Function.h"
24 : #include "llvm/GlobalVariable.h"
25 : #include "llvm/Target/TargetData.h"
26 : using namespace clang;
27 : using namespace CodeGen;
28 :
29 : namespace {
30 85: class ConstStructBuilder {
31 : CodeGenModule &CGM;
32 : CodeGenFunction *CGF;
33 :
34 : bool Packed;
35 :
36 : unsigned NextFieldOffsetInBytes;
37 :
38 : unsigned LLVMStructAlignment;
39 :
40 : std::vector<llvm::Constant *> Elements;
41 :
42 85: ConstStructBuilder(CodeGenModule &CGM, CodeGenFunction *CGF)
43 : : CGM(CGM), CGF(CGF), Packed(false), NextFieldOffsetInBytes(0),
44 85: LLVMStructAlignment(1) { }
45 :
46 : bool AppendField(const FieldDecl *Field, uint64_t FieldOffset,
47 126: const Expr *InitExpr) {
48 126: uint64_t FieldOffsetInBytes = FieldOffset / 8;
49 :
50 : assert(NextFieldOffsetInBytes <= FieldOffsetInBytes
0: branch 0 not taken
126: branch 1 taken
51 126: && "Field offset mismatch!");
52 :
53 : // Emit the field.
54 126: llvm::Constant *C = CGM.EmitConstantExpr(InitExpr, Field->getType(), CGF);
0: branch 0 not taken
126: branch 1 taken
55 126: if (!C)
56 0: return false;
57 :
58 126: unsigned FieldAlignment = getAlignment(C);
59 :
60 : // Round up the field offset to the alignment of the field type.
61 : uint64_t AlignedNextFieldOffsetInBytes =
62 126: llvm::RoundUpToAlignment(NextFieldOffsetInBytes, FieldAlignment);
63 :
2: branch 0 taken
124: branch 1 taken
64 126: if (AlignedNextFieldOffsetInBytes > FieldOffsetInBytes) {
0: branch 0 not taken
2: branch 1 taken
65 2: assert(!Packed && "Alignment is wrong even with a packed struct!");
66 :
67 : // Convert the struct to a packed struct.
68 2: ConvertStructToPacked();
69 :
70 2: AlignedNextFieldOffsetInBytes = NextFieldOffsetInBytes;
71 : }
72 :
0: branch 0 not taken
126: branch 1 taken
73 126: if (AlignedNextFieldOffsetInBytes < FieldOffsetInBytes) {
74 : // We need to append padding.
75 0: AppendPadding(FieldOffsetInBytes - NextFieldOffsetInBytes);
76 :
77 : assert(NextFieldOffsetInBytes == FieldOffsetInBytes &&
0: branch 0 not taken
0: branch 1 not taken
78 0: "Did not add enough padding!");
79 :
80 0: AlignedNextFieldOffsetInBytes = NextFieldOffsetInBytes;
81 : }
82 :
83 : // Add the field.
84 126: Elements.push_back(C);
85 126: NextFieldOffsetInBytes = AlignedNextFieldOffsetInBytes + getSizeInBytes(C);
86 :
2: branch 0 taken
124: branch 1 taken
87 126: if (Packed)
0: branch 0 not taken
2: branch 1 taken
88 2: assert(LLVMStructAlignment == 1 && "Packed struct not byte-aligned!");
89 : else
90 124: LLVMStructAlignment = std::max(LLVMStructAlignment, FieldAlignment);
91 :
92 126: return true;
93 : }
94 :
95 : bool AppendBitField(const FieldDecl *Field, uint64_t FieldOffset,
96 15: const Expr *InitExpr) {
97 : llvm::ConstantInt *CI =
98 : cast_or_null<llvm::ConstantInt>(CGM.EmitConstantExpr(InitExpr,
99 : Field->getType(),
100 15: CGF));
101 : // FIXME: Can this ever happen?
0: branch 0 not taken
15: branch 1 taken
102 15: if (!CI)
103 0: return false;
104 :
0: branch 0 not taken
15: branch 1 taken
105 15: if (FieldOffset > NextFieldOffsetInBytes * 8) {
106 : // We need to add padding.
107 : uint64_t NumBytes =
108 : llvm::RoundUpToAlignment(FieldOffset -
109 0: NextFieldOffsetInBytes * 8, 8) / 8;
110 :
111 0: AppendPadding(NumBytes);
112 : }
113 :
114 : uint64_t FieldSize =
115 15: Field->getBitWidth()->EvaluateAsInt(CGM.getContext()).getZExtValue();
116 :
117 15: llvm::APInt FieldValue = CI->getValue();
118 :
119 : // Promote the size of FieldValue if necessary
120 : // FIXME: This should never occur, but currently it can because initializer
121 : // constants are cast to bool, and because clang is not enforcing bitfield
122 : // width limits.
0: branch 1 not taken
15: branch 2 taken
123 15: if (FieldSize > FieldValue.getBitWidth())
124 0: FieldValue.zext(FieldSize);
125 :
126 : // Truncate the size of FieldValue to the bit field size.
14: branch 1 taken
1: branch 2 taken
127 15: if (FieldSize < FieldValue.getBitWidth())
128 14: FieldValue.trunc(FieldSize);
129 :
1: branch 0 taken
14: branch 1 taken
130 15: if (FieldOffset < NextFieldOffsetInBytes * 8) {
131 : // Either part of the field or the entire field can go into the previous
132 : // byte.
1: branch 1 taken
0: branch 2 not taken
133 1: assert(!Elements.empty() && "Elements can't be empty!");
134 :
135 : unsigned BitsInPreviousByte =
136 1: NextFieldOffsetInBytes * 8 - FieldOffset;
137 :
138 : bool FitsCompletelyInPreviousByte =
139 1: BitsInPreviousByte >= FieldValue.getBitWidth();
140 :
141 1: llvm::APInt Tmp = FieldValue;
142 :
0: branch 0 not taken
1: branch 1 taken
143 1: if (!FitsCompletelyInPreviousByte) {
144 0: unsigned NewFieldWidth = FieldSize - BitsInPreviousByte;
145 :
0: branch 2 not taken
0: branch 3 not taken
146 0: if (CGM.getTargetData().isBigEndian()) {
147 0: Tmp = Tmp.lshr(NewFieldWidth);
148 0: Tmp.trunc(BitsInPreviousByte);
149 :
150 : // We want the remaining high bits.
151 0: FieldValue.trunc(NewFieldWidth);
152 : } else {
153 0: Tmp.trunc(BitsInPreviousByte);
154 :
155 : // We want the remaining low bits.
156 0: FieldValue = FieldValue.lshr(BitsInPreviousByte);
157 0: FieldValue.trunc(NewFieldWidth);
158 : }
159 : }
160 :
161 1: Tmp.zext(8);
0: branch 2 not taken
1: branch 3 taken
162 1: if (CGM.getTargetData().isBigEndian()) {
0: branch 0 not taken
0: branch 1 not taken
163 0: if (FitsCompletelyInPreviousByte)
164 0: Tmp = Tmp.shl(BitsInPreviousByte - FieldValue.getBitWidth());
165 : } else {
166 1: Tmp = Tmp.shl(8 - BitsInPreviousByte);
167 : }
168 :
169 : // Or in the bits that go into the previous byte.
1: branch 2 taken
0: branch 3 not taken
170 1: if (llvm::ConstantInt *Val = dyn_cast<llvm::ConstantInt>(Elements.back()))
171 1: Tmp |= Val->getValue();
172 : else
0: branch 2 not taken
0: branch 3 not taken
173 0: assert(isa<llvm::UndefValue>(Elements.back()));
174 :
175 1: Elements.back() = llvm::ConstantInt::get(CGM.getLLVMContext(), Tmp);
176 :
1: branch 0 taken
0: branch 1 not taken
177 1: if (FitsCompletelyInPreviousByte)
0: branch 1 not taken
1: branch 2 taken
178 1: return true;
179 : }
180 :
19: branch 2 taken
14: branch 3 taken
181 33: while (FieldValue.getBitWidth() > 8) {
182 19: llvm::APInt Tmp;
183 :
0: branch 2 not taken
19: branch 3 taken
184 19: if (CGM.getTargetData().isBigEndian()) {
185 : // We want the high bits.
186 0: Tmp = FieldValue;
187 0: Tmp = Tmp.lshr(Tmp.getBitWidth() - 8);
188 0: Tmp.trunc(8);
189 : } else {
190 : // We want the low bits.
191 19: Tmp = FieldValue;
192 19: Tmp.trunc(8);
193 :
194 19: FieldValue = FieldValue.lshr(8);
195 : }
196 :
197 19: Elements.push_back(llvm::ConstantInt::get(CGM.getLLVMContext(), Tmp));
198 19: NextFieldOffsetInBytes++;
199 :
200 19: FieldValue.trunc(FieldValue.getBitWidth() - 8);
201 : }
202 :
203 : assert(FieldValue.getBitWidth() > 0 &&
14: branch 1 taken
0: branch 2 not taken
204 14: "Should have at least one bit left!");
205 : assert(FieldValue.getBitWidth() <= 8 &&
14: branch 1 taken
0: branch 2 not taken
206 14: "Should not have more than a byte left!");
207 :
12: branch 1 taken
2: branch 2 taken
208 14: if (FieldValue.getBitWidth() < 8) {
0: branch 2 not taken
12: branch 3 taken
209 12: if (CGM.getTargetData().isBigEndian()) {
210 0: unsigned BitWidth = FieldValue.getBitWidth();
211 :
212 0: FieldValue.zext(8);
213 0: FieldValue = FieldValue << (8 - BitWidth);
214 : } else
215 12: FieldValue.zext(8);
216 : }
217 :
218 : // Append the last element.
219 : Elements.push_back(llvm::ConstantInt::get(CGM.getLLVMContext(),
220 14: FieldValue));
221 14: NextFieldOffsetInBytes++;
222 14: return true;
223 : }
224 :
225 83: void AppendPadding(uint64_t NumBytes) {
17: branch 0 taken
66: branch 1 taken
226 83: if (!NumBytes)
227 66: return;
228 :
229 17: const llvm::Type *Ty = llvm::Type::getInt8Ty(CGM.getLLVMContext());
16: branch 0 taken
1: branch 1 taken
230 17: if (NumBytes > 1)
231 16: Ty = llvm::ArrayType::get(Ty, NumBytes);
232 :
233 17: llvm::Constant *C = llvm::UndefValue::get(Ty);
234 17: Elements.push_back(C);
17: branch 1 taken
0: branch 2 not taken
235 17: assert(getAlignment(C) == 1 && "Padding must have 1 byte alignment!");
236 :
237 17: NextFieldOffsetInBytes += getSizeInBytes(C);
238 : }
239 :
240 83: void AppendTailPadding(uint64_t RecordSize) {
0: branch 0 not taken
83: branch 1 taken
241 83: assert(RecordSize % 8 == 0 && "Invalid record size!");
242 :
243 83: uint64_t RecordSizeInBytes = RecordSize / 8;
0: branch 0 not taken
83: branch 1 taken
244 83: assert(NextFieldOffsetInBytes <= RecordSizeInBytes && "Size mismatch!");
245 :
246 83: unsigned NumPadBytes = RecordSizeInBytes - NextFieldOffsetInBytes;
247 83: AppendPadding(NumPadBytes);
248 83: }
249 :
250 3: void ConvertStructToPacked() {
251 3: std::vector<llvm::Constant *> PackedElements;
252 3: uint64_t ElementOffsetInBytes = 0;
253 :
6: branch 1 taken
3: branch 2 taken
254 9: for (unsigned i = 0, e = Elements.size(); i != e; ++i) {
255 6: llvm::Constant *C = Elements[i];
256 :
257 : unsigned ElementAlign =
258 6: CGM.getTargetData().getABITypeAlignment(C->getType());
259 : uint64_t AlignedElementOffsetInBytes =
260 6: llvm::RoundUpToAlignment(ElementOffsetInBytes, ElementAlign);
261 :
1: branch 0 taken
5: branch 1 taken
262 6: if (AlignedElementOffsetInBytes > ElementOffsetInBytes) {
263 : // We need some padding.
264 : uint64_t NumBytes =
265 1: AlignedElementOffsetInBytes - ElementOffsetInBytes;
266 :
267 1: const llvm::Type *Ty = llvm::Type::getInt8Ty(CGM.getLLVMContext());
0: branch 0 not taken
1: branch 1 taken
268 1: if (NumBytes > 1)
269 0: Ty = llvm::ArrayType::get(Ty, NumBytes);
270 :
271 1: llvm::Constant *Padding = llvm::UndefValue::get(Ty);
272 1: PackedElements.push_back(Padding);
273 1: ElementOffsetInBytes += getSizeInBytes(Padding);
274 : }
275 :
276 6: PackedElements.push_back(C);
277 6: ElementOffsetInBytes += getSizeInBytes(C);
278 : }
279 :
280 : assert(ElementOffsetInBytes == NextFieldOffsetInBytes &&
0: branch 0 not taken
3: branch 1 taken
281 3: "Packing the struct changed its size!");
282 :
283 3: Elements = PackedElements;
284 3: LLVMStructAlignment = 1;
285 3: Packed = true;
286 3: }
287 :
288 85: bool Build(InitListExpr *ILE) {
289 85: RecordDecl *RD = ILE->getType()->getAs<RecordType>()->getDecl();
290 85: const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
291 :
292 85: unsigned FieldNo = 0;
293 85: unsigned ElementNo = 0;
143: branch 3 taken
85: branch 4 taken
143: branch 6 taken
0: branch 7 not taken
143: branch 8 taken
85: branch 9 taken
294 313: for (RecordDecl::field_iterator Field = RD->field_begin(),
295 85: FieldEnd = RD->field_end();
296 : ElementNo < ILE->getNumInits() && Field != FieldEnd;
297 : ++Field, ++FieldNo) {
10: branch 1 taken
133: branch 2 taken
2: branch 5 taken
8: branch 6 taken
2: branch 7 taken
141: branch 8 taken
298 143: if (RD->isUnion() && ILE->getInitializedFieldInUnion() != *Field)
299 2: continue;
300 :
15: branch 2 taken
126: branch 3 taken
301 141: if (Field->isBitField()) {
0: branch 2 not taken
15: branch 3 taken
302 15: if (!Field->getIdentifier())
303 0: continue;
304 :
0: branch 4 not taken
15: branch 5 taken
305 15: if (!AppendBitField(*Field, Layout.getFieldOffset(FieldNo),
306 : ILE->getInit(ElementNo)))
307 0: return false;
308 : } else {
0: branch 4 not taken
126: branch 5 taken
309 126: if (!AppendField(*Field, Layout.getFieldOffset(FieldNo),
310 : ILE->getInit(ElementNo)))
311 0: return false;
312 : }
313 :
314 141: ElementNo++;
315 : }
316 :
317 85: uint64_t LayoutSizeInBytes = Layout.getSize() / 8;
318 :
2: branch 0 taken
83: branch 1 taken
319 85: if (NextFieldOffsetInBytes > LayoutSizeInBytes) {
320 : // If the struct is bigger than the size of the record type,
321 : // we must have a flexible array member at the end.
322 : assert(RD->hasFlexibleArrayMember() &&
2: branch 1 taken
0: branch 2 not taken
323 2: "Must have flexible array member if struct is bigger than type!");
324 :
325 : // No tail padding is necessary.
326 2: return true;
327 : }
328 :
329 : uint64_t LLVMSizeInBytes = llvm::RoundUpToAlignment(NextFieldOffsetInBytes,
330 83: LLVMStructAlignment);
331 :
332 : // Check if we need to convert the struct to a packed struct.
83: branch 0 taken
0: branch 1 not taken
1: branch 2 taken
82: branch 3 taken
333 83: if (NextFieldOffsetInBytes <= LayoutSizeInBytes &&
334 : LLVMSizeInBytes > LayoutSizeInBytes) {
0: branch 0 not taken
1: branch 1 taken
335 1: assert(!Packed && "Size mismatch!");
336 :
337 1: ConvertStructToPacked();
338 : assert(NextFieldOffsetInBytes == LayoutSizeInBytes &&
0: branch 0 not taken
1: branch 1 taken
339 1: "Converting to packed did not help!");
340 : }
341 :
342 : // Append tail padding if necessary.
343 83: AppendTailPadding(Layout.getSize());
344 :
345 : assert(Layout.getSize() / 8 == NextFieldOffsetInBytes &&
83: branch 1 taken
0: branch 2 not taken
346 83: "Tail padding mismatch!");
347 :
348 83: return true;
349 : }
350 :
351 228: unsigned getAlignment(const llvm::Constant *C) const {
4: branch 0 taken
224: branch 1 taken
352 228: if (Packed)
353 4: return 1;
354 :
355 224: return CGM.getTargetData().getABITypeAlignment(C->getType());
356 : }
357 :
358 235: uint64_t getSizeInBytes(const llvm::Constant *C) const {
359 235: return CGM.getTargetData().getTypeAllocSize(C->getType());
360 : }
361 :
362 : public:
363 : static llvm::Constant *BuildStruct(CodeGenModule &CGM, CodeGenFunction *CGF,
364 85: InitListExpr *ILE) {
365 85: ConstStructBuilder Builder(CGM, CGF);
366 :
0: branch 1 not taken
85: branch 2 taken
367 85: if (!Builder.Build(ILE))
368 0: return 0;
369 :
370 : llvm::Constant *Result =
371 : llvm::ConstantStruct::get(CGM.getLLVMContext(),
372 85: Builder.Elements, Builder.Packed);
373 :
374 : assert(llvm::RoundUpToAlignment(Builder.NextFieldOffsetInBytes,
375 : Builder.getAlignment(Result)) ==
85: branch 3 taken
0: branch 4 not taken
376 85: Builder.getSizeInBytes(Result) && "Size mismatch!");
377 :
378 170: return Result;
379 : }
380 : };
381 :
382 : class ConstExprEmitter :
383 : public StmtVisitor<ConstExprEmitter, llvm::Constant*> {
384 : CodeGenModule &CGM;
385 : CodeGenFunction *CGF;
386 : llvm::LLVMContext &VMContext;
387 : public:
388 453: ConstExprEmitter(CodeGenModule &cgm, CodeGenFunction *cgf)
389 453: : CGM(cgm), CGF(cgf), VMContext(cgm.getLLVMContext()) {
390 453: }
391 :
392 : //===--------------------------------------------------------------------===//
393 : // Visitor Methods
394 : //===--------------------------------------------------------------------===//
395 :
396 22: llvm::Constant *VisitStmt(Stmt *S) {
397 22: return 0;
398 : }
399 :
400 0: llvm::Constant *VisitParenExpr(ParenExpr *PE) {
401 0: return Visit(PE->getSubExpr());
402 : }
403 :
404 1: llvm::Constant *VisitCompoundLiteralExpr(CompoundLiteralExpr *E) {
405 1: return Visit(E->getInitializer());
406 : }
407 :
408 10: llvm::Constant *EmitMemberFunctionPointer(CXXMethodDecl *MD) {
10: branch 1 taken
0: branch 2 not taken
409 10: assert(MD->isInstance() && "Member function must not be static!");
410 :
411 10: MD = MD->getCanonicalDecl();
412 :
413 : const llvm::Type *PtrDiffTy =
414 10: CGM.getTypes().ConvertType(CGM.getContext().getPointerDiffType());
415 :
416 : llvm::Constant *Values[2];
417 :
418 : // Get the function pointer (or index if this is a virtual function).
6: branch 1 taken
4: branch 2 taken
419 10: if (MD->isVirtual()) {
420 6: uint64_t Index = CGM.getVtableInfo().getMethodVtableIndex(MD);
421 :
422 : // Itanium C++ ABI 2.3:
423 : // For a non-virtual function, this field is a simple function pointer.
424 : // For a virtual function, it is 1 plus the virtual table offset
425 : // (in bytes) of the function, represented as a ptrdiff_t.
426 6: Values[0] = llvm::ConstantInt::get(PtrDiffTy, (Index * 8) + 1);
427 : } else {
428 4: const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>();
429 : const llvm::Type *Ty =
430 : CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(MD),
431 4: FPT->isVariadic());
432 :
433 4: llvm::Constant *FuncPtr = CGM.GetAddrOfFunction(MD, Ty);
434 4: Values[0] = llvm::ConstantExpr::getPtrToInt(FuncPtr, PtrDiffTy);
435 : }
436 :
437 : // The adjustment will always be 0.
438 10: Values[1] = llvm::ConstantInt::get(PtrDiffTy, 0);
439 :
440 : return llvm::ConstantStruct::get(CGM.getLLVMContext(),
441 10: Values, 2, /*Packed=*/false);
442 : }
443 :
444 11: llvm::Constant *VisitUnaryAddrOf(UnaryOperator *E) {
11: branch 0 taken
0: branch 1 not taken
445 11: if (const MemberPointerType *MPT =
446 11: E->getType()->getAs<MemberPointerType>()) {
447 11: QualType T = MPT->getPointeeType();
448 11: DeclRefExpr *DRE = cast<DeclRefExpr>(E->getSubExpr());
449 :
450 11: NamedDecl *ND = DRE->getDecl();
10: branch 2 taken
1: branch 3 taken
451 11: if (T->isFunctionProtoType())
452 10: return EmitMemberFunctionPointer(cast<CXXMethodDecl>(ND));
453 :
454 : // We have a pointer to data member.
455 1: return CGM.EmitPointerToDataMember(cast<FieldDecl>(ND));
456 : }
457 :
458 0: return 0;
459 : }
460 :
461 3: llvm::Constant *VisitBinSub(BinaryOperator *E) {
462 : // This must be a pointer/pointer subtraction. This only happens for
463 : // address of label.
1: branch 4 taken
2: branch 5 taken
0: branch 10 not taken
1: branch 11 taken
2: branch 12 taken
1: branch 13 taken
464 3: if (!isa<AddrLabelExpr>(E->getLHS()->IgnoreParenNoopCasts(CGM.getContext())) ||
465 : !isa<AddrLabelExpr>(E->getRHS()->IgnoreParenNoopCasts(CGM.getContext())))
466 2: return 0;
467 :
468 : llvm::Constant *LHS = CGM.EmitConstantExpr(E->getLHS(),
469 1: E->getLHS()->getType(), CGF);
470 : llvm::Constant *RHS = CGM.EmitConstantExpr(E->getRHS(),
471 1: E->getRHS()->getType(), CGF);
472 :
473 1: const llvm::Type *ResultType = ConvertType(E->getType());
474 1: LHS = llvm::ConstantExpr::getPtrToInt(LHS, ResultType);
475 1: RHS = llvm::ConstantExpr::getPtrToInt(RHS, ResultType);
476 :
477 : // No need to divide by element size, since addr of label is always void*,
478 : // which has size 1 in GNUish.
479 1: return llvm::ConstantExpr::getSub(LHS, RHS);
480 : }
481 :
482 15: llvm::Constant *VisitCastExpr(CastExpr* E) {
4: branch 1 taken
1: branch 2 taken
1: branch 3 taken
2: branch 4 taken
7: branch 5 taken
483 15: switch (E->getCastKind()) {
484 : case CastExpr::CK_ToUnion: {
485 : // GCC cast to union extension
486 : assert(E->getType()->isUnionType() &&
4: branch 3 taken
0: branch 4 not taken
487 4: "Destination type is not union type!");
488 4: const llvm::Type *Ty = ConvertType(E->getType());
489 4: Expr *SubExpr = E->getSubExpr();
490 :
491 : llvm::Constant *C =
492 4: CGM.EmitConstantExpr(SubExpr, SubExpr->getType(), CGF);
0: branch 0 not taken
4: branch 1 taken
493 4: if (!C)
494 0: return 0;
495 :
496 : // Build a struct with the union sub-element as the first member,
497 : // and padded to the appropriate size
498 4: std::vector<llvm::Constant*> Elts;
499 4: std::vector<const llvm::Type*> Types;
500 4: Elts.push_back(C);
501 4: Types.push_back(C->getType());
502 4: unsigned CurSize = CGM.getTargetData().getTypeAllocSize(C->getType());
503 4: unsigned TotalSize = CGM.getTargetData().getTypeAllocSize(Ty);
504 :
0: branch 0 not taken
4: branch 1 taken
505 4: assert(CurSize <= TotalSize && "Union size mismatch!");
2: branch 0 taken
2: branch 1 taken
506 4: if (unsigned NumPadBytes = TotalSize - CurSize) {
507 2: const llvm::Type *Ty = llvm::Type::getInt8Ty(VMContext);
2: branch 0 taken
0: branch 1 not taken
508 2: if (NumPadBytes > 1)
509 2: Ty = llvm::ArrayType::get(Ty, NumPadBytes);
510 :
511 2: Elts.push_back(llvm::UndefValue::get(Ty));
512 2: Types.push_back(Ty);
513 : }
514 :
515 : llvm::StructType* STy =
516 4: llvm::StructType::get(C->getType()->getContext(), Types, false);
517 4: return llvm::ConstantStruct::get(STy, Elts);
518 : }
519 : case CastExpr::CK_NullToMemberPointer:
520 1: return CGM.EmitNullConstant(E->getType());
521 :
522 : case CastExpr::CK_BaseToDerivedMemberPointer: {
523 1: Expr *SubExpr = E->getSubExpr();
524 :
525 : const MemberPointerType *SrcTy =
526 1: SubExpr->getType()->getAs<MemberPointerType>();
527 : const MemberPointerType *DestTy =
528 1: E->getType()->getAs<MemberPointerType>();
529 :
530 : const CXXRecordDecl *BaseClass =
531 1: cast<CXXRecordDecl>(cast<RecordType>(SrcTy->getClass())->getDecl());
532 : const CXXRecordDecl *DerivedClass =
533 1: cast<CXXRecordDecl>(cast<RecordType>(DestTy->getClass())->getDecl());
534 :
1: branch 3 taken
0: branch 4 not taken
535 1: if (SrcTy->getPointeeType()->isFunctionProtoType()) {
536 : llvm::Constant *C =
537 1: CGM.EmitConstantExpr(SubExpr, SubExpr->getType(), CGF);
0: branch 0 not taken
1: branch 1 taken
538 1: if (!C)
539 0: return 0;
540 :
541 1: llvm::ConstantStruct *CS = cast<llvm::ConstantStruct>(C);
542 :
543 : // Check if we need to update the adjustment.
1: branch 0 taken
0: branch 1 not taken
544 1: if (llvm::Constant *Offset =
545 1: CGM.GetNonVirtualBaseClassOffset(DerivedClass, BaseClass)) {
546 : llvm::Constant *Values[2];
547 :
548 1: Values[0] = CS->getOperand(0);
549 1: Values[1] = llvm::ConstantExpr::getAdd(CS->getOperand(1), Offset);
550 : return llvm::ConstantStruct::get(CGM.getLLVMContext(), Values, 2,
551 1: /*Packed=*/false);
552 : }
553 :
554 0: return CS;
555 : }
556 : }
557 :
558 : case CastExpr::CK_BitCast:
559 : // This must be a member function pointer cast.
560 2: return Visit(E->getSubExpr());
561 :
562 : default: {
563 : // FIXME: This should be handled by the CK_NoOp cast kind.
564 : // Explicit and implicit no-op casts
565 7: QualType Ty = E->getType(), SubTy = E->getSubExpr()->getType();
2: branch 2 taken
5: branch 3 taken
566 7: if (CGM.getContext().hasSameUnqualifiedType(Ty, SubTy))
567 2: return Visit(E->getSubExpr());
568 :
569 : // Handle integer->integer casts for address-of-label differences.
5: branch 2 taken
0: branch 3 not taken
5: branch 6 taken
0: branch 7 not taken
3: branch 8 taken
2: branch 9 taken
3: branch 10 taken
2: branch 11 taken
570 5: if (Ty->isIntegerType() && SubTy->isIntegerType() &&
571 : CGF) {
572 3: llvm::Value *Src = Visit(E->getSubExpr());
2: branch 0 taken
1: branch 1 taken
573 3: if (Src == 0) return 0;
574 :
575 : // Use EmitScalarConversion to perform the conversion.
576 1: return cast<llvm::Constant>(CGF->EmitScalarConversion(Src, SubTy, Ty));
577 : }
578 :
579 2: return 0;
580 : }
581 : }
582 : }
583 :
584 0: llvm::Constant *VisitCXXDefaultArgExpr(CXXDefaultArgExpr *DAE) {
585 0: return Visit(DAE->getExpr());
586 : }
587 :
588 54: llvm::Constant *EmitArrayInitialization(InitListExpr *ILE) {
589 54: std::vector<llvm::Constant*> Elts;
590 : const llvm::ArrayType *AType =
591 54: cast<llvm::ArrayType>(ConvertType(ILE->getType()));
592 54: unsigned NumInitElements = ILE->getNumInits();
593 : // FIXME: Check for wide strings
594 : // FIXME: Check for NumInitElements exactly equal to 1??
52: branch 0 taken
2: branch 1 taken
49: branch 4 taken
3: branch 5 taken
0: branch 8 not taken
49: branch 9 taken
2: branch 14 taken
1: branch 15 taken
2: branch 16 taken
52: branch 17 taken
595 54: if (NumInitElements > 0 &&
596 : (isa<StringLiteral>(ILE->getInit(0)) ||
597 : isa<ObjCEncodeExpr>(ILE->getInit(0))) &&
598 : ILE->getType()->getArrayElementTypeNoTypeQual()->isCharType())
599 2: return Visit(ILE->getInit(0));
600 52: const llvm::Type *ElemTy = AType->getElementType();
601 52: unsigned NumElements = AType->getNumElements();
602 :
603 : // Initialising an array requires us to automatically
604 : // initialise any elements that have not been initialised explicitly
605 52: unsigned NumInitableElts = std::min(NumInitElements, NumElements);
606 :
607 : // Copy initializer elements.
608 52: unsigned i = 0;
609 52: bool RewriteType = false;
167: branch 0 taken
52: branch 1 taken
610 219: for (; i < NumInitableElts; ++i) {
611 167: Expr *Init = ILE->getInit(i);
612 167: llvm::Constant *C = CGM.EmitConstantExpr(Init, Init->getType(), CGF);
0: branch 0 not taken
167: branch 1 taken
613 167: if (!C)
614 0: return 0;
615 167: RewriteType |= (C->getType() != ElemTy);
616 167: Elts.push_back(C);
617 : }
618 :
619 : // Initialize remaining array elements.
620 : // FIXME: This doesn't handle member pointers correctly!
131: branch 0 taken
52: branch 1 taken
621 183: for (; i < NumElements; ++i)
622 131: Elts.push_back(llvm::Constant::getNullValue(ElemTy));
623 :
0: branch 0 not taken
52: branch 1 taken
624 52: if (RewriteType) {
625 : // FIXME: Try to avoid packing the array
626 0: std::vector<const llvm::Type*> Types;
0: branch 1 not taken
0: branch 2 not taken
627 0: for (unsigned i = 0; i < Elts.size(); ++i)
628 0: Types.push_back(Elts[i]->getType());
629 : const llvm::StructType *SType = llvm::StructType::get(AType->getContext(),
630 0: Types, true);
631 0: return llvm::ConstantStruct::get(SType, Elts);
632 : }
633 :
634 52: return llvm::ConstantArray::get(AType, Elts);
635 : }
636 :
637 85: llvm::Constant *EmitStructInitialization(InitListExpr *ILE) {
638 85: return ConstStructBuilder::BuildStruct(CGM, CGF, ILE);
639 : }
640 :
641 0: llvm::Constant *EmitUnionInitialization(InitListExpr *ILE) {
642 0: return ConstStructBuilder::BuildStruct(CGM, CGF, ILE);
643 : }
644 :
645 0: llvm::Constant *VisitImplicitValueInitExpr(ImplicitValueInitExpr* E) {
646 0: return CGM.EmitNullConstant(E->getType());
647 : }
648 :
649 142: llvm::Constant *VisitInitListExpr(InitListExpr *ILE) {
3: branch 3 taken
139: branch 4 taken
650 142: if (ILE->getType()->isScalarType()) {
651 : // We have a scalar in braces. Just use the first element.
3: branch 1 taken
0: branch 2 not taken
652 3: if (ILE->getNumInits() > 0) {
653 3: Expr *Init = ILE->getInit(0);
654 3: return CGM.EmitConstantExpr(Init, Init->getType(), CGF);
655 : }
656 0: return CGM.EmitNullConstant(ILE->getType());
657 : }
658 :
54: branch 3 taken
85: branch 4 taken
659 139: if (ILE->getType()->isArrayType())
660 54: return EmitArrayInitialization(ILE);
661 :
85: branch 3 taken
0: branch 4 not taken
662 85: if (ILE->getType()->isRecordType())
663 85: return EmitStructInitialization(ILE);
664 :
0: branch 3 not taken
0: branch 4 not taken
665 0: if (ILE->getType()->isUnionType())
666 0: return EmitUnionInitialization(ILE);
667 :
668 : // If ILE was a constant vector, we would have handled it already.
0: branch 3 not taken
0: branch 4 not taken
669 0: if (ILE->getType()->isVectorType())
670 0: return 0;
671 :
672 0: assert(0 && "Unable to handle InitListExpr");
673 : // Get rid of control reaches end of void function warning.
674 : // Not reached.
675 : return 0;
676 : }
677 :
678 124: llvm::Constant *VisitCXXConstructExpr(CXXConstructExpr *E) {
94: branch 2 taken
30: branch 3 taken
679 124: if (!E->getConstructor()->isTrivial())
680 94: return 0;
681 :
682 30: QualType Ty = E->getType();
683 :
684 : // FIXME: We should not have to call getBaseElementType here.
685 : const RecordType *RT =
686 30: CGM.getContext().getBaseElementType(Ty)->getAs<RecordType>();
687 30: const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
688 :
689 : // If the class doesn't have a trivial destructor, we can't emit it as a
690 : // constant expr.
1: branch 1 taken
29: branch 2 taken
691 30: if (!RD->hasTrivialDestructor())
692 1: return 0;
693 :
694 : // Only copy and default constructors can be trivial.
695 :
696 :
3: branch 1 taken
26: branch 2 taken
697 29: if (E->getNumArgs()) {
3: branch 1 taken
0: branch 2 not taken
698 3: assert(E->getNumArgs() == 1 && "trivial ctor with > 1 argument");
699 : assert(E->getConstructor()->isCopyConstructor() &&
3: branch 2 taken
0: branch 3 not taken
700 3: "trivial ctor has argument but isn't a copy ctor");
701 :
702 3: Expr *Arg = E->getArg(0);
703 : assert(CGM.getContext().hasSameUnqualifiedType(Ty, Arg->getType()) &&
3: branch 3 taken
0: branch 4 not taken
704 3: "argument to copy ctor is of wrong type");
705 :
706 3: return Visit(Arg);
707 : }
708 :
709 26: return CGM.EmitNullConstant(Ty);
710 : }
711 :
712 19: llvm::Constant *VisitStringLiteral(StringLiteral *E) {
19: branch 3 taken
0: branch 4 not taken
713 19: assert(!E->getType()->isPointerType() && "Strings are always arrays");
714 :
715 : // This must be a string initializing an array in a static initializer.
716 : // Don't emit it as the address of the string, emit the string data itself
717 : // as an inline array.
718 : return llvm::ConstantArray::get(VMContext,
719 19: CGM.GetStringForStringLiteral(E), false);
720 : }
721 :
722 4: llvm::Constant *VisitObjCEncodeExpr(ObjCEncodeExpr *E) {
723 : // This must be an @encode initializing an array in a static initializer.
724 : // Don't emit it as the address of the string, emit the string data itself
725 : // as an inline array.
726 4: std::string Str;
727 4: CGM.getContext().getObjCEncodingForType(E->getEncodedType(), Str);
728 4: const ConstantArrayType *CAT = cast<ConstantArrayType>(E->getType());
729 :
730 : // Resize the string to the right size, adding zeros at the end, or
731 : // truncating as needed.
732 4: Str.resize(CAT->getSize().getZExtValue(), '\0');
733 4: return llvm::ConstantArray::get(VMContext, Str, false);
734 : }
735 :
736 0: llvm::Constant *VisitUnaryExtension(const UnaryOperator *E) {
737 0: return Visit(E->getSubExpr());
738 : }
739 :
740 : // Utility methods
741 77: const llvm::Type *ConvertType(QualType T) {
742 77: return CGM.getTypes().ConvertType(T);
743 : }
744 :
745 : public:
746 128: llvm::Constant *EmitLValue(Expr *E) {
0: branch 1 not taken
3: branch 2 taken
67: branch 3 taken
18: branch 4 taken
7: branch 5 taken
4: branch 6 taken
1: branch 7 taken
14: branch 8 taken
11: branch 9 taken
3: branch 10 taken
747 128: switch (E->getStmtClass()) {
748 0: default: break;
749 : case Expr::CompoundLiteralExprClass: {
750 : // Note that due to the nature of compound literals, this is guaranteed
751 : // to be the only use of the variable, so we just generate it here.
752 3: CompoundLiteralExpr *CLE = cast<CompoundLiteralExpr>(E);
753 3: llvm::Constant* C = Visit(CLE->getInitializer());
754 : // FIXME: "Leaked" on failure.
3: branch 0 taken
0: branch 1 not taken
755 3: if (C)
756 : C = new llvm::GlobalVariable(CGM.getModule(), C->getType(),
757 : E->getType().isConstant(CGM.getContext()),
758 : llvm::GlobalValue::InternalLinkage,
759 : C, ".compoundliteral", 0, false,
760 3: E->getType().getAddressSpace());
761 3: return C;
762 : }
763 : case Expr::DeclRefExprClass: {
764 67: NamedDecl *Decl = cast<DeclRefExpr>(E)->getDecl();
29: branch 1 taken
38: branch 2 taken
765 67: if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(Decl))
766 29: return CGM.GetAddrOfFunction(FD);
38: branch 1 taken
0: branch 2 not taken
767 38: if (const VarDecl* VD = dyn_cast<VarDecl>(Decl)) {
768 : // We can never refer to a variable with local storage.
38: branch 1 taken
0: branch 2 not taken
769 38: if (!VD->hasLocalStorage()) {
4: branch 1 taken
34: branch 2 taken
1: branch 4 taken
3: branch 5 taken
35: branch 6 taken
3: branch 7 taken
770 38: if (VD->isFileVarDecl() || VD->hasExternalStorage())
771 35: return CGM.GetAddrOfGlobalVar(VD);
3: branch 1 taken
0: branch 2 not taken
772 3: else if (VD->isBlockVarDecl()) {
0: branch 0 not taken
3: branch 1 taken
773 3: assert(CGF && "Can't access static local vars without CGF");
774 3: return CGF->GetAddrOfStaticLocalVar(VD);
775 : }
776 : }
777 : }
778 0: break;
779 : }
780 : case Expr::StringLiteralClass:
781 18: return CGM.GetAddrOfConstantStringFromLiteral(cast<StringLiteral>(E));
782 : case Expr::ObjCEncodeExprClass:
783 7: return CGM.GetAddrOfConstantStringFromObjCEncode(cast<ObjCEncodeExpr>(E));
784 : case Expr::ObjCStringLiteralClass: {
785 4: ObjCStringLiteral* SL = cast<ObjCStringLiteral>(E);
786 : llvm::Constant *C =
787 4: CGM.getObjCRuntime().GenerateConstantString(SL->getString());
788 4: return llvm::ConstantExpr::getBitCast(C, ConvertType(E->getType()));
789 : }
790 : case Expr::PredefinedExprClass: {
791 1: unsigned Type = cast<PredefinedExpr>(E)->getIdentType();
1: branch 0 taken
0: branch 1 not taken
792 1: if (CGF) {
793 1: LValue Res = CGF->EmitPredefinedFunctionName(Type);
794 1: return cast<llvm::Constant>(Res.getAddress());
0: branch 0 not taken
0: branch 1 not taken
795 0: } else if (Type == PredefinedExpr::PrettyFunction) {
796 0: return CGM.GetAddrOfConstantCString("top level", ".tmp");
797 : }
798 :
799 0: return CGM.GetAddrOfConstantCString("", ".tmp");
800 : }
801 : case Expr::AddrLabelExprClass: {
0: branch 0 not taken
14: branch 1 taken
802 14: assert(CGF && "Invalid address of label expression outside function.");
803 : llvm::Constant *Ptr =
804 14: CGF->GetAddrOfLabel(cast<AddrLabelExpr>(E)->getLabel());
805 14: return llvm::ConstantExpr::getBitCast(Ptr, ConvertType(E->getType()));
806 : }
807 : case Expr::CallExprClass: {
808 11: CallExpr* CE = cast<CallExpr>(E);
809 11: unsigned builtin = CE->isBuiltinCall(CGM.getContext());
0: branch 0 not taken
11: branch 1 taken
11: branch 2 taken
11: branch 3 taken
810 11: if (builtin !=
811 : Builtin::BI__builtin___CFStringMakeConstantString &&
812 : builtin !=
813 : Builtin::BI__builtin___NSStringMakeConstantString)
814 0: break;
815 11: const Expr *Arg = CE->getArg(0)->IgnoreParenCasts();
816 11: const StringLiteral *Literal = cast<StringLiteral>(Arg);
0: branch 0 not taken
11: branch 1 taken
817 11: if (builtin ==
818 : Builtin::BI__builtin___NSStringMakeConstantString) {
819 0: return CGM.getObjCRuntime().GenerateConstantString(Literal);
820 : }
821 : // FIXME: need to deal with UCN conversion issues.
822 11: return CGM.GetAddrOfConstantCFString(Literal);
823 : }
824 : case Expr::BlockExprClass: {
825 3: std::string FunctionName;
0: branch 0 not taken
3: branch 1 taken
826 3: if (CGF)
827 0: FunctionName = CGF->CurFn->getName();
828 : else
829 3: FunctionName = "global";
830 :
831 3: return CGM.GetAddrOfGlobalBlock(cast<BlockExpr>(E), FunctionName.c_str());
832 : }
833 : }
834 :
835 0: return 0;
836 : }
837 : };
838 :
839 : } // end anonymous namespace.
840 :
841 : llvm::Constant *CodeGenModule::EmitConstantExpr(const Expr *E,
842 : QualType DestType,
843 794: CodeGenFunction *CGF) {
844 794: Expr::EvalResult Result;
845 :
846 794: bool Success = false;
847 :
9: branch 2 taken
785: branch 3 taken
848 794: if (DestType->isReferenceType())
849 9: Success = E->EvaluateAsLValue(Result, Context);
850 : else
851 785: Success = E->Evaluate(Result, Context);
852 :
470: branch 0 taken
324: branch 1 taken
469: branch 2 taken
1: branch 3 taken
853 794: if (Success && !Result.HasSideEffects) {
0: branch 1 not taken
145: branch 2 taken
265: branch 3 taken
3: branch 4 taken
47: branch 5 taken
5: branch 6 taken
4: branch 7 taken
0: branch 8 not taken
854 469: switch (Result.Val.getKind()) {
855 : case APValue::Uninitialized:
856 0: assert(0 && "Constant expressions should be initialized.");
857 : return 0;
858 : case APValue::LValue: {
859 145: const llvm::Type *DestTy = getTypes().ConvertTypeForMem(DestType);
860 : llvm::Constant *Offset =
861 : llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext),
862 145: Result.Val.getLValueOffset().getQuantity());
863 :
864 : llvm::Constant *C;
128: branch 1 taken
17: branch 2 taken
865 145: if (const Expr *LVBase = Result.Val.getLValueBase()) {
866 128: C = ConstExprEmitter(*this, CGF).EmitLValue(const_cast<Expr*>(LVBase));
867 :
868 : // Apply offset if necessary.
6: branch 1 taken
122: branch 2 taken
869 128: if (!Offset->isNullValue()) {
870 6: const llvm::Type *Type = llvm::Type::getInt8PtrTy(VMContext);
871 6: llvm::Constant *Casted = llvm::ConstantExpr::getBitCast(C, Type);
872 6: Casted = llvm::ConstantExpr::getGetElementPtr(Casted, &Offset, 1);
873 6: C = llvm::ConstantExpr::getBitCast(Casted, C->getType());
874 : }
875 :
876 : // Convert to the appropriate type; this could be an lvalue for
877 : // an integer.
121: branch 1 taken
7: branch 2 taken
878 128: if (isa<llvm::PointerType>(DestTy))
879 121: return llvm::ConstantExpr::getBitCast(C, DestTy);
880 :
881 7: return llvm::ConstantExpr::getPtrToInt(C, DestTy);
882 : } else {
883 17: C = Offset;
884 :
885 : // Convert to the appropriate type; this could be an lvalue for
886 : // an integer.
17: branch 1 taken
0: branch 2 not taken
887 17: if (isa<llvm::PointerType>(DestTy))
888 17: return llvm::ConstantExpr::getIntToPtr(C, DestTy);
889 :
890 : // If the types don't match this should only be a truncate.
0: branch 1 not taken
0: branch 2 not taken
891 0: if (C->getType() != DestTy)
892 0: return llvm::ConstantExpr::getTrunc(C, DestTy);
893 :
894 0: return C;
895 : }
896 : }
897 : case APValue::Int: {
898 : llvm::Constant *C = llvm::ConstantInt::get(VMContext,
899 265: Result.Val.getInt());
900 :
3: branch 2 taken
262: branch 3 taken
901 265: if (C->getType() == llvm::Type::getInt1Ty(VMContext)) {
902 3: const llvm::Type *BoolTy = getTypes().ConvertTypeForMem(E->getType());
903 3: C = llvm::ConstantExpr::getZExt(C, BoolTy);
904 : }
905 265: return C;
906 : }
907 : case APValue::ComplexInt: {
908 : llvm::Constant *Complex[2];
909 :
910 : Complex[0] = llvm::ConstantInt::get(VMContext,
911 3: Result.Val.getComplexIntReal());
912 : Complex[1] = llvm::ConstantInt::get(VMContext,
913 3: Result.Val.getComplexIntImag());
914 :
915 : // FIXME: the target may want to specify that this is packed.
916 3: return llvm::ConstantStruct::get(VMContext, Complex, 2, false);
917 : }
918 : case APValue::Float:
919 47: return llvm::ConstantFP::get(VMContext, Result.Val.getFloat());
920 : case APValue::ComplexFloat: {
921 : llvm::Constant *Complex[2];
922 :
923 : Complex[0] = llvm::ConstantFP::get(VMContext,
924 5: Result.Val.getComplexFloatReal());
925 : Complex[1] = llvm::ConstantFP::get(VMContext,
926 5: Result.Val.getComplexFloatImag());
927 :
928 : // FIXME: the target may want to specify that this is packed.
929 5: return llvm::ConstantStruct::get(VMContext, Complex, 2, false);
930 : }
931 : case APValue::Vector: {
932 4: llvm::SmallVector<llvm::Constant *, 4> Inits;
933 4: unsigned NumElts = Result.Val.getVectorLength();
934 :
16: branch 0 taken
4: branch 1 taken
935 20: for (unsigned i = 0; i != NumElts; ++i) {
936 16: APValue &Elt = Result.Val.getVectorElt(i);
8: branch 1 taken
8: branch 2 taken
937 16: if (Elt.isInt())
938 8: Inits.push_back(llvm::ConstantInt::get(VMContext, Elt.getInt()));
939 : else
940 8: Inits.push_back(llvm::ConstantFP::get(VMContext, Elt.getFloat()));
941 : }
942 4: return llvm::ConstantVector::get(&Inits[0], Inits.size());
943 : }
944 : }
945 : }
946 :
947 325: llvm::Constant* C = ConstExprEmitter(*this, CGF).Visit(const_cast<Expr*>(E));
204: branch 0 taken
121: branch 1 taken
0: branch 4 not taken
204: branch 5 taken
0: branch 6 not taken
325: branch 7 taken
948 325: if (C && C->getType() == llvm::Type::getInt1Ty(VMContext)) {
949 0: const llvm::Type *BoolTy = getTypes().ConvertTypeForMem(E->getType());
950 0: C = llvm::ConstantExpr::getZExt(C, BoolTy);
951 : }
952 325: return C;
953 : }
954 :
955 545: static bool containsPointerToDataMember(CodeGenTypes &Types, QualType T) {
956 : // No need to check for member pointers when not compiling C++.
314: branch 2 taken
231: branch 3 taken
957 545: if (!Types.getContext().getLangOptions().CPlusPlus)
958 314: return false;
959 :
960 231: T = Types.getContext().getBaseElementType(T);
961 :
128: branch 2 taken
103: branch 3 taken
962 231: if (const RecordType *RT = T->getAs<RecordType>()) {
963 128: const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
964 :
965 : // FIXME: It would be better if there was a way to explicitly compute the
966 : // record layout instead of converting to a type.
967 128: Types.ConvertTagDeclType(RD);
968 :
969 128: const CGRecordLayout &Layout = Types.getCGRecordLayout(RD);
970 128: return Layout.containsPointerToDataMember();
971 : }
972 :
23: branch 2 taken
80: branch 3 taken
973 103: if (const MemberPointerType *MPT = T->getAs<MemberPointerType>())
974 23: return !MPT->getPointeeType()->isFunctionType();
975 :
976 80: return false;
977 : }
978 :
979 545: llvm::Constant *CodeGenModule::EmitNullConstant(QualType T) {
521: branch 2 taken
24: branch 3 taken
980 545: if (!containsPointerToDataMember(getTypes(), T))
981 521: return llvm::Constant::getNullValue(getTypes().ConvertTypeForMem(T));
982 :
5: branch 1 taken
19: branch 2 taken
983 24: if (const ConstantArrayType *CAT = Context.getAsConstantArrayType(T)) {
984 :
985 5: QualType ElementTy = CAT->getElementType();
986 :
987 5: llvm::Constant *Element = EmitNullConstant(ElementTy);
988 5: unsigned NumElements = CAT->getSize().getZExtValue();
989 5: std::vector<llvm::Constant *> Array(NumElements);
10: branch 0 taken
5: branch 1 taken
990 15: for (unsigned i = 0; i != NumElements; ++i)
991 10: Array[i] = Element;
992 :
993 : const llvm::ArrayType *ATy =
994 5: cast<llvm::ArrayType>(getTypes().ConvertTypeForMem(T));
995 5: return llvm::ConstantArray::get(ATy, Array);
996 : }
997 :
4: branch 2 taken
15: branch 3 taken
998 19: if (const RecordType *RT = T->getAs<RecordType>()) {
999 4: const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
1000 : assert(!RD->getNumBases() &&
1001 : "FIXME: Handle zero-initializing structs with bases and "
4: branch 1 taken
0: branch 2 not taken
1002 4: "pointers to data members.");
1003 : const llvm::StructType *STy =
1004 4: cast<llvm::StructType>(getTypes().ConvertTypeForMem(T));
1005 4: unsigned NumElements = STy->getNumElements();
1006 4: std::vector<llvm::Constant *> Elements(NumElements);
1007 :
4: branch 3 taken
4: branch 4 taken
1008 12: for (RecordDecl::field_iterator I = RD->field_begin(),
1009 4: E = RD->field_end(); I != E; ++I) {
1010 4: const FieldDecl *FD = *I;
1011 :
1012 4: unsigned FieldNo = getTypes().getLLVMFieldNo(FD);
1013 4: Elements[FieldNo] = EmitNullConstant(FD->getType());
1014 : }
1015 :
1016 : // Now go through all other fields and zero them out.
4: branch 0 taken
4: branch 1 taken
1017 8: for (unsigned i = 0; i != NumElements; ++i) {
0: branch 1 not taken
4: branch 2 taken
1018 4: if (!Elements[i])
1019 0: Elements[i] = llvm::Constant::getNullValue(STy->getElementType(i));
1020 : }
1021 :
1022 4: return llvm::ConstantStruct::get(STy, Elements);
1023 : }
1024 :
1025 : assert(!T->getAs<MemberPointerType>()->getPointeeType()->isFunctionType() &&
15: branch 5 taken
0: branch 6 not taken
1026 15: "Should only see pointers to data members here!");
1027 :
1028 : // Itanium C++ ABI 2.3:
1029 : // A NULL pointer is represented as -1.
1030 : return llvm::ConstantInt::get(getTypes().ConvertTypeForMem(T), -1,
1031 15: /*isSigned=*/true);
1032 : }
1033 :
1034 : llvm::Constant *
1035 18: CodeGenModule::EmitPointerToDataMember(const FieldDecl *FD) {
1036 :
1037 : // Itanium C++ ABI 2.3:
1038 : // A pointer to data member is an offset from the base address of the class
1039 : // object containing it, represented as a ptrdiff_t
1040 :
1041 18: const CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(FD->getParent());
1042 : QualType ClassType =
1043 18: getContext().getTypeDeclType(const_cast<CXXRecordDecl *>(ClassDecl));
1044 :
1045 : const llvm::StructType *ClassLTy =
1046 18: cast<llvm::StructType>(getTypes().ConvertType(ClassType));
1047 :
1048 18: unsigned FieldNo = getTypes().getLLVMFieldNo(FD);
1049 : uint64_t Offset =
1050 18: getTargetData().getStructLayout(ClassLTy)->getElementOffset(FieldNo);
1051 :
1052 : const llvm::Type *PtrDiffTy =
1053 18: getTypes().ConvertType(getContext().getPointerDiffType());
1054 :
1055 18: return llvm::ConstantInt::get(PtrDiffTy, Offset);
1056 : }
Generated: 2010-02-10 01:31 by zcov