mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-29 06:16:07 +00:00
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. llvm-svn: 54659
This commit is contained in:
parent
dafdbf77b3
commit
8b8683f9f6
@ -61,8 +61,10 @@ public:
|
||||
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) {
|
||||
|
@ -20,9 +20,10 @@ using namespace clang;
|
||||
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.
|
||||
|
@ -90,8 +90,7 @@ private:
|
||||
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 @@ llvm::Constant *CGObjCGNU::MakeGlobal(const llvm::ArrayType *Ty,
|
||||
//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");
|
||||
|
@ -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 @@ private:
|
||||
|
||||
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 @@ public:
|
||||
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 @@ llvm::Value *CGObjCMac::GetSelector(llvm::IRBuilder<> &Builder, Selector Sel) {
|
||||
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 @@ void CGObjCMac::EmitImageInfo() {
|
||||
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 @@ void CGObjCMac::EmitImageInfo() {
|
||||
"\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 @@ void CGObjCMac::FinishModule() {
|
||||
|
||||
/* *** */
|
||||
|
||||
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);
|
||||
}
|
||||
|
@ -59,8 +59,7 @@ public:
|
||||
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,
|
||||
|
Loading…
x
Reference in New Issue
Block a user