aboutsummaryrefslogtreecommitdiff
path: root/CodeGen
diff options
context:
space:
mode:
authorAnders Carlsson <andersca@mac.com>2007-08-21 00:21:21 +0000
committerAnders Carlsson <andersca@mac.com>2007-08-21 00:21:21 +0000
commitc9e2091efcb535110474434dd12015afdc3b1637 (patch)
tree25a7c51e891e0c4355d41f6c289559415ca8a4aa /CodeGen
parent7016a706c9fab0d7c1603e424c61abbff9077037 (diff)
Implement code generation for constant CFStrings.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@41206 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'CodeGen')
-rw-r--r--CodeGen/CGBuiltin.cpp12
-rw-r--r--CodeGen/CodeGenModule.cpp58
-rw-r--r--CodeGen/CodeGenModule.h6
-rw-r--r--CodeGen/CodeGenTypes.cpp5
-rw-r--r--CodeGen/CodeGenTypes.h4
5 files changed, 82 insertions, 3 deletions
diff --git a/CodeGen/CGBuiltin.cpp b/CodeGen/CGBuiltin.cpp
index 0095bdef48..769fa5ce3b 100644
--- a/CodeGen/CGBuiltin.cpp
+++ b/CodeGen/CGBuiltin.cpp
@@ -15,6 +15,7 @@
#include "CodeGenModule.h"
#include "clang/AST/Builtins.h"
#include "clang/AST/Expr.h"
+#include "llvm/Constant.h"
using namespace clang;
using namespace CodeGen;
@@ -22,6 +23,17 @@ using namespace CodeGen;
RValue CodeGenFunction::EmitBuiltinExpr(unsigned builtinID, const CallExpr *E)
{
switch (builtinID) {
+ case Builtin::BI__builtin___CFStringMakeConstantString: {
+ const Expr *Arg = E->getArg(0);
+
+ while (const ParenExpr *PE = dyn_cast<const ParenExpr>(Arg))
+ Arg = PE->getSubExpr();
+
+ const StringLiteral *Literal = cast<const StringLiteral>(Arg);
+ std::string S(Literal->getStrData(), Literal->getByteLength());
+
+ return RValue::get(CGM.GetAddrOfConstantCFString(S));
+ }
default:
assert(0 && "Unknown builtin id");
}
diff --git a/CodeGen/CodeGenModule.cpp b/CodeGen/CodeGenModule.cpp
index 44cb91dd1d..74c7d43e1d 100644
--- a/CodeGen/CodeGenModule.cpp
+++ b/CodeGen/CodeGenModule.cpp
@@ -26,7 +26,7 @@ using namespace CodeGen;
CodeGenModule::CodeGenModule(ASTContext &C, llvm::Module &M)
- : Context(C), TheModule(M), Types(C, M) {}
+ : Context(C), TheModule(M), Types(C, M), CFConstantStringClassRef(0) {}
llvm::Constant *CodeGenModule::GetAddrOfGlobalDecl(const Decl *D) {
// See if it is already in the map.
@@ -113,3 +113,59 @@ llvm::Function *CodeGenModule::getMemCpyFn() {
}
return MemCpyFn = llvm::Intrinsic::getDeclaration(&TheModule, IID);
}
+
+llvm::Constant *CodeGenModule::GetAddrOfConstantCFString(const std::string &str)
+{
+ llvm::StringMapEntry<llvm::Constant *> &Entry =
+ CFConstantStringMap.GetOrCreateValue(&str[0], &str[str.length()]);
+
+ if (Entry.getValue())
+ return Entry.getValue();
+
+ std::vector<llvm::Constant*> Fields;
+
+ if (!CFConstantStringClassRef) {
+ const llvm::Type *Ty = getTypes().ConvertType(getContext().IntTy);
+ Ty = llvm::ArrayType::get(Ty, 0);
+
+ CFConstantStringClassRef =
+ new llvm::GlobalVariable(Ty, false,
+ llvm::GlobalVariable::ExternalLinkage, 0,
+ "__CFConstantStringClassReference",
+ &getModule());
+ }
+
+ // Class pointer.
+ llvm::Constant *Zero = llvm::Constant::getNullValue(llvm::Type::Int32Ty);
+ llvm::Constant *Zeros[] = { Zero, Zero };
+ llvm::Constant *C =
+ llvm::ConstantExpr::getGetElementPtr(CFConstantStringClassRef, Zeros, 2);
+ Fields.push_back(C);
+
+ // Flags.
+ const llvm::Type *Ty = getTypes().ConvertType(getContext().IntTy);
+ Fields.push_back(llvm::ConstantInt::get(Ty, 1992));
+
+ // String pointer.
+ C = llvm::ConstantArray::get(str);
+ C = new llvm::GlobalVariable(C->getType(), true,
+ llvm::GlobalValue::InternalLinkage,
+ C, ".str", &getModule());
+
+ C = llvm::ConstantExpr::getGetElementPtr(C, Zeros, 2);
+ Fields.push_back(C);
+
+ // String length.
+ Ty = getTypes().ConvertType(getContext().LongTy);
+ Fields.push_back(llvm::ConstantInt::get(Ty, str.length()));
+
+ // The struct.
+ Ty = getTypes().ConvertType(getContext().getCFConstantStringType());
+ C = llvm::ConstantStruct::get(cast<llvm::StructType>(Ty), Fields);
+ C = new llvm::GlobalVariable(C->getType(), true,
+ llvm::GlobalVariable::InternalLinkage,
+ C, "", &getModule());
+
+ Entry.setValue(C);
+ return C;
+}
diff --git a/CodeGen/CodeGenModule.h b/CodeGen/CodeGenModule.h
index fbebdcfcf5..97d6a02f47 100644
--- a/CodeGen/CodeGenModule.h
+++ b/CodeGen/CodeGenModule.h
@@ -16,6 +16,7 @@
#include "CodeGenTypes.h"
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/StringMap.h"
namespace llvm {
class Module;
@@ -40,6 +41,9 @@ class CodeGenModule {
llvm::Function *MemCpyFn;
llvm::DenseMap<const Decl*, llvm::Constant*> GlobalDeclMap;
+
+ llvm::StringMap<llvm::Constant*> CFConstantStringMap;
+ llvm::Constant *CFConstantStringClassRef;
public:
CodeGenModule(ASTContext &C, llvm::Module &M);
@@ -48,7 +52,7 @@ public:
CodeGenTypes &getTypes() { return Types; }
llvm::Constant *GetAddrOfGlobalDecl(const Decl *D);
-
+ llvm::Constant *GetAddrOfConstantCFString(const std::string& str);
llvm::Function *getMemCpyFn();
void EmitFunction(const FunctionDecl *FD);
diff --git a/CodeGen/CodeGenTypes.cpp b/CodeGen/CodeGenTypes.cpp
index 6a2bb1e273..3888538864 100644
--- a/CodeGen/CodeGenTypes.cpp
+++ b/CodeGen/CodeGenTypes.cpp
@@ -136,8 +136,11 @@ const llvm::Type *CodeGenTypes::ConvertType(QualType T) {
case Type::Tagged:
const TagType &TT = cast<TagType>(Ty);
const TagDecl *TD = TT.getDecl();
- llvm::Type *ResultType;
+ llvm::Type *&ResultType = TagDeclTypes[TD];
+ if (ResultType)
+ return ResultType;
+
if (!TD->isDefinition()) {
ResultType = llvm::OpaqueType::get();
} else {
diff --git a/CodeGen/CodeGenTypes.h b/CodeGen/CodeGenTypes.h
index 1e3416c98c..1f6cbd8701 100644
--- a/CodeGen/CodeGenTypes.h
+++ b/CodeGen/CodeGenTypes.h
@@ -14,6 +14,7 @@
#ifndef CODEGEN_CODEGENTYPES_H
#define CODEGEN_CODEGENTYPES_H
+#include "llvm/ADT/DenseMap.h"
#include <vector>
namespace llvm {
@@ -23,6 +24,7 @@ namespace llvm {
namespace clang {
class ASTContext;
+ class TagDecl;
class TargetInfo;
class QualType;
class FunctionTypeProto;
@@ -35,6 +37,8 @@ class CodeGenTypes {
ASTContext &Context;
TargetInfo &Target;
llvm::Module& TheModule;
+
+ llvm::DenseMap<const TagDecl*, llvm::Type*> TagDeclTypes;
public:
CodeGenTypes(ASTContext &Ctx, llvm::Module &M);