diff options
author | Anders Carlsson <andersca@mac.com> | 2007-08-21 00:21:21 +0000 |
---|---|---|
committer | Anders Carlsson <andersca@mac.com> | 2007-08-21 00:21:21 +0000 |
commit | c9e2091efcb535110474434dd12015afdc3b1637 (patch) | |
tree | 25a7c51e891e0c4355d41f6c289559415ca8a4aa /CodeGen | |
parent | 7016a706c9fab0d7c1603e424c61abbff9077037 (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.cpp | 12 | ||||
-rw-r--r-- | CodeGen/CodeGenModule.cpp | 58 | ||||
-rw-r--r-- | CodeGen/CodeGenModule.h | 6 | ||||
-rw-r--r-- | CodeGen/CodeGenTypes.cpp | 5 | ||||
-rw-r--r-- | CodeGen/CodeGenTypes.h | 4 |
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); |