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
21using namespace clang;
22using namespace clang::CIRGen;
23
24Address 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
70void 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
102void 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

source code of clang/lib/CIR/CodeGen/CIRGenClass.cpp