[cfe-commits] r54659 - in /cfe/trunk/lib/CodeGen: CGExprConstant.cpp CGObjC.cpp CGObjCGNU.cpp CGObjCMac.cpp CGObjCRuntime.h
Daniel Dunbar
daniel at zuster.org
Mon Aug 11 17:12:39 PDT 2008
Author: ddunbar
Date: Mon Aug 11 19:12:39 2008
New Revision: 54659
URL: http://llvm.org/viewvc/llvm-project?rev=54659&view=rev
Log:
Add ObjC constant string support for NeXT.
Changed CGObjCRuntime::GenerateConstantString interface to take
std::string instead of char* and size.
Change ObjC functions which call on GenerateConstantString to bitcast
result to appropriate type.
Modified:
cfe/trunk/lib/CodeGen/CGExprConstant.cpp
cfe/trunk/lib/CodeGen/CGObjC.cpp
cfe/trunk/lib/CodeGen/CGObjCGNU.cpp
cfe/trunk/lib/CodeGen/CGObjCMac.cpp
cfe/trunk/lib/CodeGen/CGObjCRuntime.h
Modified: cfe/trunk/lib/CodeGen/CGExprConstant.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprConstant.cpp?rev=54659&r1=54658&r2=54659&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprConstant.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprConstant.cpp Mon Aug 11 19:12:39 2008
@@ -61,8 +61,10 @@
return llvm::ConstantInt::get(ConvertType(E->getType()), E->getValue());
}
llvm::Constant *VisitObjCStringLiteral(const ObjCStringLiteral *E) {
- return CGM.getObjCRuntime().GenerateConstantString(
- E->getString()->getStrData(), E->getString()->getByteLength());
+ std::string S(E->getString()->getStrData(),
+ E->getString()->getByteLength());
+ llvm::Constant *C = CGM.getObjCRuntime().GenerateConstantString(S);
+ return llvm::ConstantExpr::getBitCast(C, ConvertType(E->getType()));
}
llvm::Constant *VisitCompoundLiteralExpr(CompoundLiteralExpr *E) {
Modified: cfe/trunk/lib/CodeGen/CGObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjC.cpp?rev=54659&r1=54658&r2=54659&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGObjC.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGObjC.cpp Mon Aug 11 19:12:39 2008
@@ -20,9 +20,10 @@
using namespace CodeGen;
/// Emits an instance of NSConstantString representing the object.
-llvm::Value *CodeGenFunction::EmitObjCStringLiteral(const ObjCStringLiteral *E){
- return CGM.getObjCRuntime().GenerateConstantString(
- E->getString()->getStrData(), E->getString()->getByteLength());
+llvm::Value *CodeGenFunction::EmitObjCStringLiteral(const ObjCStringLiteral *E) {
+ std::string String(E->getString()->getStrData(), E->getString()->getByteLength());
+ llvm::Constant *C = CGM.getObjCRuntime().GenerateConstantString(String);
+ return llvm::ConstantExpr::getBitCast(C, ConvertType(E->getType()));
}
/// Emit a selector.
Modified: cfe/trunk/lib/CodeGen/CGObjCGNU.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjCGNU.cpp?rev=54659&r1=54658&r2=54659&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGObjCGNU.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGObjCGNU.cpp Mon Aug 11 19:12:39 2008
@@ -90,8 +90,7 @@
std::vector<llvm::Constant*> &V, const std::string &Name="");
public:
CGObjCGNU(CodeGen::CodeGenModule &cgm);
- virtual llvm::Constant *GenerateConstantString(const char *String,
- const size_t length);
+ virtual llvm::Constant *GenerateConstantString(const std::string &String);
virtual llvm::Value *GenerateMessageSend(llvm::IRBuilder<> &Builder,
const llvm::Type *ReturnTy,
llvm::Value *Sender,
@@ -248,13 +247,11 @@
//TODO: In case there are any crazy people still using the GNU runtime without
//an OpenStep implementation, this should let them select their own class for
//constant strings.
-llvm::Constant *CGObjCGNU::GenerateConstantString(const char *String, const
- size_t length) {
- std::string Str(String, String +length);
+llvm::Constant *CGObjCGNU::GenerateConstantString(const std::string &Str) {
std::vector<llvm::Constant*> Ivars;
Ivars.push_back(NULLPtr);
Ivars.push_back(MakeConstantString(Str));
- Ivars.push_back(llvm::ConstantInt::get(IntTy, length));
+ Ivars.push_back(llvm::ConstantInt::get(IntTy, Str.size()));
llvm::Constant *ObjCStr = MakeGlobal(
llvm::StructType::get(PtrToInt8Ty, PtrToInt8Ty, IntTy, NULL),
Ivars, ".objc_str");
Modified: cfe/trunk/lib/CodeGen/CGObjCMac.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjCMac.cpp?rev=54659&r1=54658&r2=54659&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGObjCMac.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGObjCMac.cpp Mon Aug 11 19:12:39 2008
@@ -14,17 +14,43 @@
#include "CGObjCRuntime.h"
#include "CodeGenModule.h"
+#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/Basic/LangOptions.h"
+#include "llvm/Module.h"
#include "llvm/Support/IRBuilder.h"
using namespace clang;
namespace {
+
+/// ObjCTypesHelper - Helper class that encapsulates lazy
+/// construction of varies types used during ObjC generation.
+class ObjCTypesHelper {
+private:
+ CodeGen::CodeGenModule &CGM;
+
+ const llvm::StructType *CFStringType;
+ llvm::Constant *CFConstantStringClassReference;
+
+public:
+ const llvm::Type *LongTy;
+
+public:
+ ObjCTypesHelper(CodeGen::CodeGenModule &cgm);
+ ~ObjCTypesHelper();
+
+ llvm::Constant *getCFConstantStringClassReference();
+ const llvm::StructType *getCFStringType();
+};
+
class CGObjCMac : public CodeGen::CGObjCRuntime {
private:
- CodeGen::CodeGenModule &CGM;
+ CodeGen::CodeGenModule &CGM;
+ ObjCTypesHelper ObjCTypes;
+ /// ObjCABI - FIXME: Not sure yet.
+ unsigned ObjCABI;
/// UsedGlobals - list of globals to pack into the llvm.used metadata
/// to prevent them from being clobbered.
@@ -40,8 +66,7 @@
public:
CGObjCMac(CodeGen::CodeGenModule &cgm);
- virtual llvm::Constant *GenerateConstantString(const char *String,
- const size_t length);
+ virtual llvm::Constant *GenerateConstantString(const std::string &String);
virtual llvm::Value *GenerateMessageSend(llvm::IRBuilder<> &Builder,
const llvm::Type *ReturnTy,
@@ -108,9 +133,32 @@
virtual llvm::Function *ModuleInitFunction();
};
} // end anonymous namespace
+
+/* *** Helper Functions *** */
+
+/// getConstantGEP() - Help routine to construct simple GEPs.
+static llvm::Constant *getConstantGEP(llvm::Constant *C,
+ unsigned idx0,
+ unsigned idx1) {
+ llvm::Value *Idxs[] = {
+ llvm::ConstantInt::get(llvm::Type::Int32Ty, idx0),
+ llvm::ConstantInt::get(llvm::Type::Int32Ty, idx1)
+ };
+ return llvm::ConstantExpr::getGetElementPtr(C, Idxs, 2);
+}
+
+/* *** CGObjCMac Public Interface *** */
-CGObjCMac::CGObjCMac(CodeGen::CodeGenModule &cgm) : CGM(cgm) {
- EmitImageInfo();
+CGObjCMac::CGObjCMac(CodeGen::CodeGenModule &cgm)
+ : CGM(cgm),
+ ObjCTypes(cgm),
+ ObjCABI(1)
+{
+ // FIXME: How does this get set in GCC? And what does it even mean?
+ if (ObjCTypes.LongTy != CGM.getTypes().ConvertType(CGM.getContext().IntTy))
+ ObjCABI = 2;
+
+ EmitImageInfo();
}
// This has to perform the lookup every time, since posing and related
@@ -127,11 +175,51 @@
return 0;
}
-/// Generate an NSConstantString object.
-llvm::Constant *CGObjCMac::GenerateConstantString(const char *String,
- const size_t length) {
- assert(0 && "Cannot generate constant string for Mac runtime.");
- return 0;
+/// Generate a constant CFString object.
+/*
+ struct __builtin_CFString {
+ const int *isa; // point to __CFConstantStringClassReference
+ int flags;
+ const char *str;
+ long length;
+ };
+*/
+
+llvm::Constant *CGObjCMac::GenerateConstantString(const std::string &String) {
+ // FIXME: I have no idea what this constant is (it is a magic
+ // constant in GCC as well). Most likely the encoding of the string
+ // and at least one part of it relates to UTF-16. Is this just the
+ // code for UTF-8? Where is this handled for us?
+ // See: <rdr://2996215>
+ unsigned flags = 0x07c8;
+
+ // FIXME: Use some machinery to unique this. We can't reuse the CGM
+ // one since we put them in a different section.
+ llvm::Constant *StringC = llvm::ConstantArray::get(String);
+ llvm::Constant *StringGV =
+ new llvm::GlobalVariable(StringC->getType(), true,
+ llvm::GlobalValue::InternalLinkage,
+ StringC, ".str", &CGM.getModule());
+ llvm::Constant *Values[4] = {
+ ObjCTypes.getCFConstantStringClassReference(),
+ llvm::ConstantInt::get(llvm::Type::Int32Ty, flags),
+ getConstantGEP(StringGV, 0, 0), // Decay array -> ptr
+ llvm::ConstantInt::get(ObjCTypes.LongTy, String.size())
+ };
+
+ llvm::Constant *CFStringC =
+ llvm::ConstantStruct::get(ObjCTypes.getCFStringType(),
+ std::vector<llvm::Constant*>(Values, Values+4));
+
+ llvm::GlobalVariable *CFStringGV =
+ new llvm::GlobalVariable(CFStringC->getType(), true,
+ llvm::GlobalValue::InternalLinkage,
+ CFStringC, "",
+ &CGM.getModule());
+
+ CFStringGV->setSection("__DATA, __cfstring");
+
+ return CFStringGV;
}
/// Generates a message send where the super is the receiver. This is
@@ -249,8 +337,6 @@
if (CGM.getLangOptions().getGCMode() == LangOptions::GCOnly)
flags |= eImageInfo_GCOnly;
- fprintf(stderr, "flags: %d (%d)\n", flags, CGM.getLangOptions().getGCMode());
-
// Emitted as int[2];
llvm::Constant *values[2] = {
llvm::ConstantInt::get(llvm::Type::Int32Ty, version),
@@ -264,7 +350,11 @@
"\01L_OBJC_IMAGE_INFO",
&CGM.getModule());
- GV->setSection("__OBJC, __image_info,regular");
+ if (ObjCABI == 1) {
+ GV->setSection("__OBJC, __image_info,regular");
+ } else {
+ GV->setSection("__DATA, __objc_imageinfo, regular, no_dead_strip");
+ }
UsedGlobals.push_back(GV);
}
@@ -291,6 +381,50 @@
/* *** */
+ObjCTypesHelper::ObjCTypesHelper(CodeGen::CodeGenModule &cgm)
+ : CGM(cgm),
+ CFStringType(0),
+ CFConstantStringClassReference(0),
+ LongTy(CGM.getTypes().ConvertType(CGM.getContext().LongTy))
+{
+}
+
+ObjCTypesHelper::~ObjCTypesHelper() {
+}
+
+const llvm::StructType *ObjCTypesHelper::getCFStringType() {
+ if (!CFStringType) {
+ CFStringType =
+ llvm::StructType::get(llvm::PointerType::getUnqual(llvm::Type::Int32Ty),
+ llvm::Type::Int32Ty,
+ llvm::PointerType::getUnqual(llvm::Type::Int8Ty),
+ LongTy,
+ NULL);
+
+ CGM.getModule().addTypeName("struct.__builtin_CFString", CFStringType);
+ }
+
+ return CFStringType;
+}
+
+llvm::Constant *ObjCTypesHelper::getCFConstantStringClassReference() {
+ if (!CFConstantStringClassReference) {
+ llvm::GlobalValue *GV =
+ new llvm::GlobalVariable(llvm::ArrayType::get(llvm::Type::Int32Ty, 0),
+ false,
+ llvm::GlobalValue::ExternalLinkage,
+ 0, "__CFConstantStringClassReference",
+ &CGM.getModule());
+
+ // Decay to pointer.
+ CFConstantStringClassReference = getConstantGEP(GV, 0, 0);
+ }
+
+ return CFConstantStringClassReference;
+}
+
+/* *** */
+
CodeGen::CGObjCRuntime *CodeGen::CreateMacObjCRuntime(CodeGen::CodeGenModule &CGM){
return new CGObjCMac(CGM);
}
Modified: cfe/trunk/lib/CodeGen/CGObjCRuntime.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjCRuntime.h?rev=54659&r1=54658&r2=54659&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGObjCRuntime.h (original)
+++ cfe/trunk/lib/CodeGen/CGObjCRuntime.h Mon Aug 11 19:12:39 2008
@@ -59,8 +59,7 @@
virtual llvm::Value *GetSelector(BuilderType &Builder,
Selector Sel) =0;
/// Generate a constant string object
- virtual llvm::Constant *GenerateConstantString(const char *String,
- const size_t Length) = 0;
+ virtual llvm::Constant *GenerateConstantString(const std::string &String) = 0;
/// Generate a category. A category contains a list of methods (and
/// accompanying metadata) and a list of protocols.
virtual void GenerateCategory(const char *ClassName, const char *CategoryName,
More information about the cfe-commits
mailing list