1 | //===----------------------------------------------------------------------===// |
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 contains code dealing with C++ code generation of classes |
10 | // |
11 | //===----------------------------------------------------------------------===// |
12 | |
13 | #include "CIRGenCXXABI.h" |
14 | #include "CIRGenFunction.h" |
15 | |
16 | #include "clang/AST/ExprCXX.h" |
17 | #include "clang/AST/RecordLayout.h" |
18 | #include "clang/AST/Type.h" |
19 | #include "clang/CIR/MissingFeatures.h" |
20 | |
21 | using namespace clang; |
22 | using namespace clang::CIRGen; |
23 | |
24 | Address CIRGenFunction::getAddressOfBaseClass( |
25 | Address value, const CXXRecordDecl *derived, |
26 | llvm::iterator_range<CastExpr::path_const_iterator> path, |
27 | bool nullCheckValue, SourceLocation loc) { |
28 | assert(!path.empty() && "Base path should not be empty!" ); |
29 | |
30 | if ((*path.begin())->isVirtual()) { |
31 | // The implementation here is actually complete, but let's flag this |
32 | // as an error until the rest of the virtual base class support is in place. |
33 | cgm.errorNYI(loc, "getAddrOfBaseClass: virtual base" ); |
34 | return Address::invalid(); |
35 | } |
36 | |
37 | // Compute the static offset of the ultimate destination within its |
38 | // allocating subobject (the virtual base, if there is one, or else |
39 | // the "complete" object that we see). |
40 | CharUnits nonVirtualOffset = |
41 | cgm.computeNonVirtualBaseClassOffset(derivedClass: derived, path); |
42 | |
43 | // Get the base pointer type. |
44 | mlir::Type baseValueTy = convertType((path.end()[-1])->getType()); |
45 | assert(!cir::MissingFeatures::addressSpace()); |
46 | |
47 | // The if statement here is redundant now, but it will be needed when we add |
48 | // support for virtual base classes. |
49 | // If there is no virtual base, use cir.base_class_addr. It takes care of |
50 | // the adjustment and the null pointer check. |
51 | if (nonVirtualOffset.isZero()) { |
52 | assert(!cir::MissingFeatures::sanitizers()); |
53 | return builder.createBaseClassAddr(getLoc(loc), value, baseValueTy, 0, |
54 | /*assumeNotNull=*/true); |
55 | } |
56 | |
57 | assert(!cir::MissingFeatures::sanitizers()); |
58 | |
59 | // Apply the offset |
60 | value = builder.createBaseClassAddr(getLoc(loc), value, baseValueTy, |
61 | nonVirtualOffset.getQuantity(), |
62 | /*assumeNotNull=*/true); |
63 | |
64 | // Cast to the destination type. |
65 | value = value.withElementType(builder, baseValueTy); |
66 | |
67 | return value; |
68 | } |
69 | |
70 | void CIRGenFunction::emitCXXConstructorCall(const clang::CXXConstructorDecl *d, |
71 | clang::CXXCtorType type, |
72 | bool forVirtualBase, |
73 | bool delegating, |
74 | AggValueSlot thisAVS, |
75 | const clang::CXXConstructExpr *e) { |
76 | CallArgList args; |
77 | Address thisAddr = thisAVS.getAddress(); |
78 | QualType thisType = d->getThisType(); |
79 | mlir::Value thisPtr = thisAddr.getPointer(); |
80 | |
81 | assert(!cir::MissingFeatures::addressSpace()); |
82 | |
83 | args.add(RValue::rvalue: get(thisPtr), type: thisType); |
84 | |
85 | // In LLVM Codegen: If this is a trivial constructor, just emit what's needed. |
86 | // If this is a union copy constructor, we must emit a memcpy, because the AST |
87 | // does not model that copy. |
88 | assert(!cir::MissingFeatures::isMemcpyEquivalentSpecialMember()); |
89 | |
90 | const FunctionProtoType *fpt = d->getType()->castAs<FunctionProtoType>(); |
91 | |
92 | assert(!cir::MissingFeatures::opCallArgEvaluationOrder()); |
93 | |
94 | emitCallArgs(args, prototype: fpt, argRange: e->arguments(), callee: e->getConstructor(), |
95 | /*ParamsToSkip=*/paramsToSkip: 0); |
96 | |
97 | assert(!cir::MissingFeatures::sanitizers()); |
98 | emitCXXConstructorCall(d, type, forVirtualBase, delegating, thisAddr, args, |
99 | e->getExprLoc()); |
100 | } |
101 | |
102 | void CIRGenFunction::emitCXXConstructorCall( |
103 | const CXXConstructorDecl *d, CXXCtorType type, bool forVirtualBase, |
104 | bool delegating, Address thisAddr, CallArgList &args, SourceLocation loc) { |
105 | |
106 | const CXXRecordDecl *crd = d->getParent(); |
107 | |
108 | // If this is a call to a trivial default constructor: |
109 | // In LLVM: do nothing. |
110 | // In CIR: emit as a regular call, other later passes should lower the |
111 | // ctor call into trivial initialization. |
112 | assert(!cir::MissingFeatures::isTrivialCtorOrDtor()); |
113 | |
114 | assert(!cir::MissingFeatures::isMemcpyEquivalentSpecialMember()); |
115 | |
116 | bool passPrototypeArgs = true; |
117 | |
118 | // Check whether we can actually emit the constructor before trying to do so. |
119 | if (d->getInheritedConstructor()) { |
120 | cgm.errorNYI(d->getSourceRange(), |
121 | "emitCXXConstructorCall: inherited constructor" ); |
122 | return; |
123 | } |
124 | |
125 | // Insert any ABI-specific implicit constructor arguments. |
126 | assert(!cir::MissingFeatures::implicitConstructorArgs()); |
127 | |
128 | // Emit the call. |
129 | auto calleePtr = cgm.getAddrOfCXXStructor(GlobalDecl(d, type)); |
130 | const CIRGenFunctionInfo &info = cgm.getTypes().arrangeCXXConstructorCall( |
131 | args, d, ctorKind: type, passProtoArgs: passPrototypeArgs); |
132 | CIRGenCallee callee = CIRGenCallee::forDirect(calleePtr, GlobalDecl(d, type)); |
133 | cir::CIRCallOpInterface c; |
134 | emitCall(info, callee, ReturnValueSlot(), args, &c, getLoc(loc)); |
135 | |
136 | if (cgm.getCodeGenOpts().OptimizationLevel != 0 && !crd->isDynamicClass() && |
137 | type != Ctor_Base && cgm.getCodeGenOpts().StrictVTablePointers) |
138 | cgm.errorNYI(d->getSourceRange(), "vtable assumption loads" ); |
139 | } |
140 | |