From: Chris Lattner Date: Sat, 1 Mar 2008 08:50:34 +0000 (+0000) Subject: Add codegen support for ObjC message expressions with the GNU runtime. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=0f984268b05edab2cc555a427c441baa9c252658;p=clang Add codegen support for ObjC message expressions with the GNU runtime. Patch by David Chisnall! git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@47790 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/CodeGen/CGObjCGNU.cpp b/CodeGen/CGObjCGNU.cpp new file mode 100644 index 0000000000..f0d6f554d5 --- /dev/null +++ b/CodeGen/CGObjCGNU.cpp @@ -0,0 +1,97 @@ +//===------- CGObjCGNU.cpp - Emit LLVM Code from ASTs for a Module --------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This provides Objective-C code generation targetting the GNU runtime. +// +//===----------------------------------------------------------------------===// + +#include "CGObjCRuntime.h" +#include "llvm/Module.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/LLVMBuilder.h" +#include "llvm/ADT/SmallVector.h" + +using namespace clang::CodeGen; +using namespace clang; + +CGObjCRuntime::~CGObjCRuntime() {} + +namespace { +class CGObjCGNU : public CGObjCRuntime { +private: + llvm::Module &TheModule; +public: + CGObjCGNU(llvm::Module &M) : TheModule(M) {}; + virtual llvm::Value *generateMessageSend(llvm::LLVMFoldingBuilder &Builder, + const llvm::Type *ReturnTy, + llvm::Value *Receiver, + llvm::Constant *Selector, + llvm::Value** ArgV, + unsigned ArgC); +}; +} // end anonymous namespace + +// Generate code for a message send expression on the GNU runtime. +// BIG FAT WARNING: Much of this code will need factoring out later. +// FIXME: This currently only handles id returns. Other return types +// need some explicit casting. +llvm::Value *CGObjCGNU::generateMessageSend(llvm::LLVMFoldingBuilder &Builder, + const llvm::Type *ReturnTy, + llvm::Value *Receiver, + llvm::Constant *Selector, + llvm::Value** ArgV, + unsigned ArgC) { + // Get the selector Type. + const llvm::Type *PtrToInt8Ty = + llvm::PointerType::getUnqual(llvm::Type::Int8Ty); + std::vector Str2(2, PtrToInt8Ty); + const llvm::Type *SelStructTy = llvm::StructType::get(Str2); + const llvm::Type *SelTy = llvm::PointerType::getUnqual(SelStructTy); + + // Look up the selector. + // If we haven't got the selector lookup function, look it up now. + // TODO: Factor this out and use it to implement @selector() too. + llvm::Constant *SelFunction = + TheModule.getOrInsertFunction("sel_get_uid", SelTy, PtrToInt8Ty, NULL); + // FIXME: Selectors should be statically cached, not looked up on every call. + + // TODO: Pull this out into the caller. + llvm::Constant *Idx0 = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0); + llvm::Constant *Ops[] = {Idx0, Idx0}; + llvm::Value *SelStr = llvm::ConstantExpr::getGetElementPtr(Selector, Ops, 2); + llvm::Value *cmd = Builder.CreateCall(SelFunction, &SelStr, &SelStr+1); + + // Look up the method implementation. + std::vector impArgTypes; + impArgTypes.push_back(Receiver->getType()); + impArgTypes.push_back(SelTy); + + // Avoid an explicit cast on the IMP by getting a version that has the right + // return type. + llvm::FunctionType *impType = llvm::FunctionType::get(ReturnTy, impArgTypes, + true); + + llvm::Constant *lookupFunction = + TheModule.getOrInsertFunction("objc_msg_lookup", + llvm::PointerType::get(impType, 0), + Receiver->getType(), SelTy, NULL); + llvm::SmallVector lookupArgs; + lookupArgs.push_back(Receiver); + lookupArgs.push_back(cmd); + llvm::Value *imp = Builder.CreateCall(lookupFunction, + lookupArgs.begin(), lookupArgs.end()); + + // Call the method. + lookupArgs.insert(lookupArgs.end(), ArgV, ArgV+ArgC); + return Builder.CreateCall(imp, lookupArgs.begin(), lookupArgs.end()); +} + +CGObjCRuntime * clang::CodeGen::CreateObjCRuntime(llvm::Module &M) { + return new CGObjCGNU(M); +} diff --git a/CodeGen/CGObjCRuntime.h b/CodeGen/CGObjCRuntime.h new file mode 100644 index 0000000000..d8fc60f99c --- /dev/null +++ b/CodeGen/CGObjCRuntime.h @@ -0,0 +1,47 @@ +//===----- CGObjCRuntime.h - Emit LLVM Code from ASTs for a Module --------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This provides an abstract class for Objective-C code generation. Concrete +// subclasses of this implement code generation for specific Objective-C +// runtime libraries. +// +//===----------------------------------------------------------------------===// + +#ifndef CLANG_CODEGEN_OBCJRUNTIME_H +#define CLANG_CODEGEN_OBCJRUNTIME_H + +namespace llvm { + class LLVMFoldingBuilder; + class Constant; + class Type; + class Value; + class Module; +} + +namespace clang { +namespace CodeGen { + +// Implements runtime-specific code generation functions +class CGObjCRuntime { +public: + virtual ~CGObjCRuntime(); + + // Generate an Objective-C message send operation + virtual llvm::Value *generateMessageSend(llvm::LLVMFoldingBuilder &Builder, + const llvm::Type *ReturnTy, + llvm::Value *Receiver, + llvm::Constant *Selector, + llvm::Value** ArgV, + unsigned ArgC) = 0; +}; + +CGObjCRuntime *CreateObjCRuntime(llvm::Module &M); +} +} +#endif