mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-12-01 01:31:26 +00:00
"Support for Objective-C message sends which return structures. Also includes a small fix for constant string handling that should have been in the last patch (sorry!) and a hook for generating selectors (rest of this implementation to follow in the next patch)."
Patch by David Chisnall! llvm-svn: 52681
This commit is contained in:
parent
6447ed3a1f
commit
b1d329da07
@ -86,6 +86,8 @@ public:
|
||||
void VisitOverloadExpr(const OverloadExpr *E);
|
||||
void VisitBinComma(const BinaryOperator *E);
|
||||
|
||||
void VisitObjCMessageExpr(ObjCMessageExpr *E);
|
||||
|
||||
|
||||
void VisitConditionalOperator(const ConditionalOperator *CO);
|
||||
void VisitInitListExpr(InitListExpr *E);
|
||||
@ -202,6 +204,16 @@ void AggExprEmitter::VisitCallExpr(const CallExpr *E)
|
||||
|
||||
EmitAggregateCopy(DestPtr, RV.getAggregateAddr(), E->getType());
|
||||
}
|
||||
void AggExprEmitter::VisitObjCMessageExpr(ObjCMessageExpr *E)
|
||||
{
|
||||
RValue RV = RValue::getAggregate(CGF.EmitObjCMessageExpr(E));
|
||||
|
||||
// If the result is ignored, don't copy from the value.
|
||||
if (DestPtr == 0)
|
||||
return;
|
||||
|
||||
EmitAggregateCopy(DestPtr, RV.getAggregateAddr(), E->getType());
|
||||
}
|
||||
|
||||
void AggExprEmitter::VisitOverloadExpr(const OverloadExpr *E)
|
||||
{
|
||||
|
@ -21,9 +21,88 @@
|
||||
using namespace clang;
|
||||
using namespace CodeGen;
|
||||
|
||||
/// Emits an instance of NSConstantString representing the object.
|
||||
llvm::Value *CodeGenFunction::EmitObjCStringLiteral(const ObjCStringLiteral *E){
|
||||
std::string S(E->getString()->getStrData(), E->getString()->getByteLength());
|
||||
return CGM.GetAddrOfConstantCFString(S);
|
||||
return CGM.getObjCRuntime()->GenerateConstantString(
|
||||
E->getString()->getStrData(), E->getString()->getByteLength());
|
||||
}
|
||||
|
||||
/// Emit a selector.
|
||||
llvm::Value *CodeGenFunction::EmitObjCSelectorExpr(const ObjCSelectorExpr *E) {
|
||||
// Untyped selector.
|
||||
// Note that this implementation allows for non-constant strings to be passed
|
||||
// as arguments to @selector(). Currently, the only thing preventing this
|
||||
// behaviour is the type checking in the front end.
|
||||
return CGM.getObjCRuntime()->GetSelector(Builder,
|
||||
CGM.GetAddrOfConstantString(E->getSelector().getName()), 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
llvm::Value *CodeGenFunction::EmitObjCMessageExpr(const ObjCMessageExpr *E) {
|
||||
// Only the lookup mechanism and first two arguments of the method
|
||||
// implementation vary between runtimes. We can get the receiver and
|
||||
// arguments in generic code.
|
||||
|
||||
CGObjCRuntime *Runtime = CGM.getObjCRuntime();
|
||||
const Expr *ReceiverExpr = E->getReceiver();
|
||||
bool isSuperMessage = false;
|
||||
// Find the receiver
|
||||
llvm::Value *Receiver;
|
||||
if (!ReceiverExpr) {
|
||||
const char * classname = E->getClassName()->getName();
|
||||
if (!strcmp(classname, "super")) {
|
||||
classname = E->getMethodDecl()->getClassInterface()->getName();
|
||||
}
|
||||
llvm::Value *ClassName = CGM.GetAddrOfConstantString(classname);
|
||||
ClassName = Builder.CreateStructGEP(ClassName, 0);
|
||||
Receiver = Runtime->LookupClass(Builder, ClassName);
|
||||
} else if (dyn_cast<PreDefinedExpr>(E->getReceiver())) {
|
||||
isSuperMessage = true;
|
||||
Receiver = LoadObjCSelf();
|
||||
} else {
|
||||
Receiver = EmitScalarExpr(E->getReceiver());
|
||||
}
|
||||
|
||||
// Process the arguments
|
||||
unsigned ArgC = E->getNumArgs();
|
||||
llvm::SmallVector<llvm::Value*, 16> Args;
|
||||
for (unsigned i = 0; i != ArgC; ++i) {
|
||||
const Expr *ArgExpr = E->getArg(i);
|
||||
QualType ArgTy = ArgExpr->getType();
|
||||
if (!hasAggregateLLVMType(ArgTy)) {
|
||||
// Scalar argument is passed by-value.
|
||||
Args.push_back(EmitScalarExpr(ArgExpr));
|
||||
} else if (ArgTy->isAnyComplexType()) {
|
||||
// Make a temporary alloca to pass the argument.
|
||||
llvm::Value *DestMem = CreateTempAlloca(ConvertType(ArgTy));
|
||||
EmitComplexExprIntoAddr(ArgExpr, DestMem, false);
|
||||
Args.push_back(DestMem);
|
||||
} else {
|
||||
llvm::Value *DestMem = CreateTempAlloca(ConvertType(ArgTy));
|
||||
EmitAggExpr(ArgExpr, DestMem, false);
|
||||
Args.push_back(DestMem);
|
||||
}
|
||||
}
|
||||
|
||||
// Get the selector string
|
||||
std::string SelStr = E->getSelector().getName();
|
||||
llvm::Constant *Selector = CGM.GetAddrOfConstantString(SelStr);
|
||||
|
||||
llvm::Value *SelPtr = Builder.CreateStructGEP(Selector, 0);
|
||||
if (isSuperMessage) {
|
||||
const ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(CurFuncDecl);
|
||||
assert(OMD && "super is only valid in an Objective-C method");
|
||||
const char *SuperClass = OMD->getClassInterface()->getSuperClass()->getName();
|
||||
return Runtime->GenerateMessageSendSuper(Builder, ConvertType(E->getType()),
|
||||
Receiver, SuperClass,
|
||||
Receiver, SelPtr,
|
||||
&Args[0], Args.size());
|
||||
}
|
||||
return Runtime->GenerateMessageSend(Builder, ConvertType(E->getType()),
|
||||
LoadObjCSelf(),
|
||||
Receiver, SelPtr,
|
||||
&Args[0], Args.size());
|
||||
}
|
||||
|
||||
/// Generate an Objective-C method. An Objective-C method is a C function with
|
||||
|
@ -405,11 +405,14 @@ llvm::Value *CGObjCGNU::GenerateMessageSend(llvm::IRBuilder &Builder,
|
||||
if (!ReturnTy->isSingleValueType()) {
|
||||
llvm::Value *Return = Builder.CreateAlloca(ReturnTy);
|
||||
Args.push_back(Return);
|
||||
return Return;
|
||||
}
|
||||
Args.push_back(Receiver);
|
||||
Args.push_back(cmd);
|
||||
Args.insert(Args.end(), ArgV, ArgV+ArgC);
|
||||
if (!ReturnTy->isSingleValueType()) {
|
||||
Builder.CreateCall(imp, Args.begin(), Args.end());
|
||||
return Args[0];
|
||||
}
|
||||
return Builder.CreateCall(imp, Args.begin(), Args.end());
|
||||
}
|
||||
|
||||
@ -887,7 +890,7 @@ llvm::Function *CGObjCGNU::MethodPreamble(
|
||||
bool isClassMethod,
|
||||
bool isVarArg) {
|
||||
std::vector<const llvm::Type*> Args;
|
||||
if (!ReturnTy->isFirstClassType() && ReturnTy != llvm::Type::VoidTy) {
|
||||
if (!ReturnTy->isSingleValueType() && ReturnTy != llvm::Type::VoidTy) {
|
||||
Args.push_back(llvm::PointerType::getUnqual(ReturnTy));
|
||||
ReturnTy = llvm::Type::VoidTy;
|
||||
}
|
||||
|
@ -451,6 +451,10 @@ public:
|
||||
bool isSplat = false);
|
||||
|
||||
llvm::Value *EmitObjCStringLiteral(const ObjCStringLiteral *E);
|
||||
llvm::Value *EmitObjCSelectorExpr(const ObjCSelectorExpr *E);
|
||||
llvm::Value *EmitObjCMessageExpr(const ObjCMessageExpr *E);
|
||||
|
||||
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// Expression Emission
|
||||
|
Loading…
Reference in New Issue
Block a user