|
25 | 25 | #include "llvm/ADT/STLExtras.h"
|
26 | 26 | #include "llvm/Analysis/ObjCARCUtil.h"
|
27 | 27 | #include "llvm/BinaryFormat/MachO.h"
|
| 28 | +#include "llvm/IR/Constants.h" |
28 | 29 | #include "llvm/IR/DataLayout.h"
|
29 | 30 | #include "llvm/IR/InlineAsm.h"
|
30 | 31 | using namespace clang;
|
@@ -1111,6 +1112,25 @@ static void emitCPPObjectAtomicGetterCall(CodeGenFunction &CGF,
|
1111 | 1112 | callee, ReturnValueSlot(), args);
|
1112 | 1113 | }
|
1113 | 1114 |
|
| 1115 | +// emitCmdValueForGetterSetterBody - Handle emitting the load necessary for |
| 1116 | +// the `_cmd` selector argument for getter/setter bodies. For direct methods, |
| 1117 | +// this returns an undefined/poison value; this matches behavior prior to `_cmd` |
| 1118 | +// being removed from the direct method ABI as the getter/setter caller would |
| 1119 | +// never load one. For non-direct methods, this emits a load of the implicit |
| 1120 | +// `_cmd` storage. |
| 1121 | +static llvm::Value *emitCmdValueForGetterSetterBody(CodeGenFunction &CGF, |
| 1122 | + ObjCMethodDecl *MD) { |
| 1123 | + if (MD->isDirectMethod()) { |
| 1124 | + // Direct methods do not have a `_cmd` argument. Emit an undefined/poison |
| 1125 | + // value. This will be passed to objc_getProperty/objc_setProperty, which |
| 1126 | + // has not appeared bothered by the `_cmd` argument being undefined before. |
| 1127 | + llvm::Type *selType = CGF.ConvertType(CGF.getContext().getObjCSelType()); |
| 1128 | + return llvm::PoisonValue::get(selType); |
| 1129 | + } |
| 1130 | + |
| 1131 | + return CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(MD->getCmdDecl()), "cmd"); |
| 1132 | +} |
| 1133 | + |
1114 | 1134 | void
|
1115 | 1135 | CodeGenFunction::generateObjCGetterBody(const ObjCImplementationDecl *classImpl,
|
1116 | 1136 | const ObjCPropertyImplDecl *propImpl,
|
@@ -1189,8 +1209,7 @@ CodeGenFunction::generateObjCGetterBody(const ObjCImplementationDecl *classImpl,
|
1189 | 1209 | // Return (ivar-type) objc_getProperty((id) self, _cmd, offset, true).
|
1190 | 1210 | // FIXME: Can't this be simpler? This might even be worse than the
|
1191 | 1211 | // corresponding gcc code.
|
1192 |
| - llvm::Value *cmd = |
1193 |
| - Builder.CreateLoad(GetAddrOfLocalVar(getterMethod->getCmdDecl()), "cmd"); |
| 1212 | + llvm::Value *cmd = emitCmdValueForGetterSetterBody(*this, getterMethod); |
1194 | 1213 | llvm::Value *self = Builder.CreateBitCast(LoadObjCSelf(), VoidPtrTy);
|
1195 | 1214 | llvm::Value *ivarOffset =
|
1196 | 1215 | EmitIvarOffset(classImpl->getClassInterface(), ivar);
|
@@ -1475,8 +1494,7 @@ CodeGenFunction::generateObjCSetterBody(const ObjCImplementationDecl *classImpl,
|
1475 | 1494 |
|
1476 | 1495 | // Emit objc_setProperty((id) self, _cmd, offset, arg,
|
1477 | 1496 | // <is-atomic>, <is-copy>).
|
1478 |
| - llvm::Value *cmd = |
1479 |
| - Builder.CreateLoad(GetAddrOfLocalVar(setterMethod->getCmdDecl())); |
| 1497 | + llvm::Value *cmd = emitCmdValueForGetterSetterBody(*this, setterMethod); |
1480 | 1498 | llvm::Value *self =
|
1481 | 1499 | Builder.CreateBitCast(LoadObjCSelf(), VoidPtrTy);
|
1482 | 1500 | llvm::Value *ivarOffset =
|
|
0 commit comments