-
Notifications
You must be signed in to change notification settings - Fork 15.4k
[CIR] Add limited support for array new #161095
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 4 commits
c8e3813
47647f6
61c116a
c597141
513fd2f
82cac01
e957c9c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -15,6 +15,7 @@ | |||||
| #include "CIRGenFunction.h" | ||||||
|
|
||||||
| #include "clang/AST/Decl.h" | ||||||
| #include "clang/AST/ExprCXX.h" | ||||||
| #include "clang/AST/GlobalDecl.h" | ||||||
|
|
||||||
| using namespace clang; | ||||||
|
|
@@ -75,3 +76,20 @@ void CIRGenCXXABI::setCXXABIThisValue(CIRGenFunction &cgf, | |||||
| assert(getThisDecl(cgf) && "no 'this' variable for function"); | ||||||
| cgf.cxxabiThisValue = thisPtr; | ||||||
| } | ||||||
|
|
||||||
| CharUnits CIRGenCXXABI::getArrayCookieSize(const CXXNewExpr *E) { | ||||||
| if (!requiresArrayCookie(E)) | ||||||
| return CharUnits::Zero(); | ||||||
|
|
||||||
| cgm.errorNYI(E->getSourceRange(), "CIRGenCXXABI::getArrayCookieSize"); | ||||||
| return CharUnits::Zero(); | ||||||
| } | ||||||
|
|
||||||
| bool CIRGenCXXABI::requiresArrayCookie(const CXXNewExpr *E) { | ||||||
|
||||||
| bool CIRGenCXXABI::requiresArrayCookie(const CXXNewExpr *E) { | |
| bool CIRGenCXXABI::requiresArrayCookie(const CXXNewExpr *e) { |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -28,6 +28,8 @@ class CIRGenCXXABI { | |||||
| CIRGenModule &cgm; | ||||||
| std::unique_ptr<clang::MangleContext> mangleContext; | ||||||
|
|
||||||
| virtual bool requiresArrayCookie(const CXXNewExpr *E); | ||||||
|
||||||
| virtual bool requiresArrayCookie(const CXXNewExpr *E); | |
| virtual bool requiresArrayCookie(const CXXNewExpr *e); |
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| virtual CharUnits getArrayCookieSize(const CXXNewExpr *E); | |
| virtual CharUnits getArrayCookieSize(const CXXNewExpr *e); |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -11,6 +11,7 @@ | |||||
| //===----------------------------------------------------------------------===// | ||||||
|
|
||||||
| #include "CIRGenCXXABI.h" | ||||||
| #include "CIRGenConstantEmitter.h" | ||||||
| #include "CIRGenFunction.h" | ||||||
|
|
||||||
| #include "clang/AST/DeclCXX.h" | ||||||
|
|
@@ -264,6 +265,19 @@ static UsualDeleteParams getUsualDeleteParams(const FunctionDecl *fd) { | |||||
| return params; | ||||||
| } | ||||||
|
|
||||||
| static CharUnits calculateCookiePadding(CIRGenFunction &cgf, | ||||||
| const CXXNewExpr *e) { | ||||||
| if (!e->isArray()) | ||||||
| return CharUnits::Zero(); | ||||||
|
|
||||||
| // No cookie is required if the operator new[] being used is the | ||||||
| // reserved placement operator new[]. | ||||||
| if (e->getOperatorNew()->isReservedGlobalPlacementOperator()) | ||||||
| return CharUnits::Zero(); | ||||||
|
|
||||||
| return cgf.cgm.getCXXABI().getArrayCookieSize(e); | ||||||
| } | ||||||
|
|
||||||
| static mlir::Value emitCXXNewAllocSize(CIRGenFunction &cgf, const CXXNewExpr *e, | ||||||
| unsigned minElements, | ||||||
| mlir::Value &numElements, | ||||||
|
|
@@ -278,8 +292,98 @@ static mlir::Value emitCXXNewAllocSize(CIRGenFunction &cgf, const CXXNewExpr *e, | |||||
| return sizeWithoutCookie; | ||||||
| } | ||||||
|
|
||||||
| cgf.cgm.errorNYI(e->getSourceRange(), "emitCXXNewAllocSize: array"); | ||||||
| return {}; | ||||||
| // The width of size_t. | ||||||
| unsigned sizeWidth = cgf.cgm.getDataLayout().getTypeSizeInBits(cgf.SizeTy); | ||||||
|
|
||||||
| // The number of elements can be have an arbitrary integer type; | ||||||
| // essentially, we need to multiply it by a constant factor, add a | ||||||
| // cookie size, and verify that the result is representable as a | ||||||
| // size_t. That's just a gloss, though, and it's wrong in one | ||||||
| // important way: if the count is negative, it's an error even if | ||||||
| // the cookie size would bring the total size >= 0. | ||||||
| // | ||||||
| // If the array size is constant, Sema will have prevented negative | ||||||
| // values and size overflow. | ||||||
|
|
||||||
| // Compute the constant factor. | ||||||
| llvm::APInt arraySizeMultiplier(sizeWidth, 1); | ||||||
| while (const ConstantArrayType *cat = | ||||||
| cgf.getContext().getAsConstantArrayType(type)) { | ||||||
| type = cat->getElementType(); | ||||||
| arraySizeMultiplier *= cat->getSize(); | ||||||
| } | ||||||
|
|
||||||
| CharUnits typeSize = cgf.getContext().getTypeSizeInChars(type); | ||||||
| llvm::APInt typeSizeMultiplier(sizeWidth, typeSize.getQuantity()); | ||||||
| typeSizeMultiplier *= arraySizeMultiplier; | ||||||
|
|
||||||
| // Figure out the cookie size. | ||||||
| llvm::APInt cookieSize(sizeWidth, | ||||||
| calculateCookiePadding(cgf, e).getQuantity()); | ||||||
|
|
||||||
| // This will be a size_t. | ||||||
| mlir::Value size; | ||||||
|
|
||||||
| // Emit the array size expression. | ||||||
| // We multiply the size of all dimensions for NumElements. | ||||||
| // e.g for 'int[2][3]', ElemType is 'int' and NumElements is 6. | ||||||
| const Expr *arraySize = *e->getArraySize(); | ||||||
| mlir::Attribute constNumElements = | ||||||
| ConstantEmitter(cgf.cgm, &cgf) | ||||||
| .emitAbstract(arraySize, arraySize->getType()); | ||||||
| if (constNumElements) { | ||||||
| // Get an APInt from the constant | ||||||
| const llvm::APInt &count = | ||||||
| mlir::cast<cir::IntAttr>(constNumElements).getValue(); | ||||||
|
|
||||||
| unsigned numElementsWidth = count.getBitWidth(); | ||||||
|
|
||||||
| // The equivalent code in CodeGen/CGExprCXX.cpp handles these cases as | ||||||
| // overflow, but they should never happen. The size argument is implicitly | ||||||
|
||||||
| // overflow, but they should never happen. The size argument is implicitly | |
| // overflow, but that should never happen. The size argument is implicitly |
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| // care because it only overflows if allocationSize does, too, and | |
| // care because it only overflows if allocationSize does too, and |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.