assert(!E->isWide() && "FIXME: Wide strings not supported yet!");
const char *StrData = E->getStrData();
unsigned Len = E->getByteLength();
-
- // FIXME: Can cache/reuse these within the module.
- llvm::Constant *C=llvm::ConstantArray::get(std::string(StrData, StrData+Len));
-
- // Create a global variable for this.
- C = new llvm::GlobalVariable(C->getType(), true,
- llvm::GlobalValue::InternalLinkage,
- C, ".str", CurFn->getParent());
- llvm::Constant *Zero = llvm::Constant::getNullValue(llvm::Type::Int32Ty);
- llvm::Constant *Zeros[] = { Zero, Zero };
- C = llvm::ConstantExpr::getGetElementPtr(C, Zeros, 2);
- return LValue::MakeAddr(C);
+ std::string StringLiteral(StrData, StrData+Len);
+ return LValue::MakeAddr(CGM.GetAddrOfConstantString(StringLiteral));
}
LValue CodeGenFunction::EmitPreDefinedLValue(const PreDefinedExpr *E) {
#include "CodeGenFunction.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
+#include "clang/Basic/LangOptions.h"
#include "clang/Basic/TargetInfo.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
using namespace CodeGen;
-CodeGenModule::CodeGenModule(ASTContext &C, llvm::Module &M,
- const llvm::TargetData &TD)
- : Context(C), TheModule(M), TheTargetData(TD),
+CodeGenModule::CodeGenModule(ASTContext &C, const LangOptions &LO,
+ llvm::Module &M, const llvm::TargetData &TD)
+ : Context(C), Features(LO), TheModule(M), TheTargetData(TD),
Types(C, M, TD), MemCpyFn(0), CFConstantStringClassRef(0) {}
llvm::Constant *CodeGenModule::GetAddrOfGlobalDecl(const ValueDecl *D) {
return 0;
}
-/// GenerateStringLiteral -- returns a pointer to the first element of a
-/// character array containing the literal.
-static llvm::Constant *GenerateStringLiteral(const StringLiteral* E,
- CodeGenModule& CGModule) {
- assert(!E->isWide() && "FIXME: Wide strings not supported yet!");
- const char *StrData = E->getStrData();
- unsigned Len = E->getByteLength();
-
- // FIXME: Can cache/reuse these within the module.
- llvm::Constant *C=llvm::ConstantArray::get(std::string(StrData, StrData+Len));
-
- // Create a global variable for this.
- C = new llvm::GlobalVariable(C->getType(), true,
- llvm::GlobalValue::InternalLinkage,
- C, ".str", &CGModule.getModule());
- llvm::Constant *Zero = llvm::Constant::getNullValue(llvm::Type::Int32Ty);
- llvm::Constant *Zeros[] = { Zero, Zero };
- C = llvm::ConstantExpr::getGetElementPtr(C, Zeros, 2);
- return C;
-}
-
/// GenerateAggregateInit - Generate a Constant initaliser for global array or
/// struct typed variables.
static llvm::Constant *GenerateAggregateInit(const InitListExpr *ILE,
// Generate constant for string literal values.
case Stmt::StringLiteralClass: {
const StringLiteral *SLiteral = cast<StringLiteral>(Expression);
- return GenerateStringLiteral(SLiteral, CGModule);
+ const char *StrData = SLiteral->getStrData();
+ unsigned Len = SLiteral->getByteLength();
+ return CGModule.GetAddrOfConstantString(std::string(StrData,
+ StrData + Len));
}
// Elide parenthesis.
Entry.setValue(GV);
return GV;
}
+
+/// GenerateWritableString -- Creates storage for a string literal
+static llvm::Constant *GenerateStringLiteral(const std::string &str,
+ bool constant,
+ CodeGenModule& CGModule) {
+ // Create Constant for this string literal
+ llvm::Constant *C=llvm::ConstantArray::get(str);
+
+ // Create a global variable for this string
+ C = new llvm::GlobalVariable(C->getType(), constant,
+ llvm::GlobalValue::InternalLinkage,
+ C, ".str", &CGModule.getModule());
+ llvm::Constant *Zero = llvm::Constant::getNullValue(llvm::Type::Int32Ty);
+ llvm::Constant *Zeros[] = { Zero, Zero };
+ C = llvm::ConstantExpr::getGetElementPtr(C, Zeros, 2);
+ return C;
+}
+
+/// CodeGenModule::GetAddrOfConstantString -- returns a pointer to the first
+/// element of a character array containing the literal.
+llvm::Constant *CodeGenModule::GetAddrOfConstantString(const std::string &str) {
+ // Don't share any string literals if writable-strings is turned on.
+ if (Features.WritableStrings)
+ return GenerateStringLiteral(str, false, *this);
+
+ llvm::StringMapEntry<llvm::Constant *> &Entry =
+ ConstantStringMap.GetOrCreateValue(&str[0], &str[str.length()]);
+
+ if (Entry.getValue())
+ return Entry.getValue();
+
+ // Create a global variable for this.
+ llvm::Constant *C = GenerateStringLiteral(str, true, *this);
+ Entry.setValue(C);
+ return C;
+}
class Decl;
class ValueDecl;
class FileVarDecl;
+ struct LangOptions;
namespace CodeGen {
/// while generating LLVM code.
class CodeGenModule {
ASTContext &Context;
+ const LangOptions &Features;
llvm::Module &TheModule;
const llvm::TargetData &TheTargetData;
CodeGenTypes Types;
llvm::Function *MemCpyFn;
llvm::DenseMap<const Decl*, llvm::Constant*> GlobalDeclMap;
-
+
llvm::StringMap<llvm::Constant*> CFConstantStringMap;
+ llvm::StringMap<llvm::Constant*> ConstantStringMap;
llvm::Constant *CFConstantStringClassRef;
std::vector<llvm::Function *> BuiltinFunctions;
public:
- CodeGenModule(ASTContext &C, llvm::Module &M, const llvm::TargetData &TD);
+ CodeGenModule(ASTContext &C, const LangOptions &Features, llvm::Module &M,
+ const llvm::TargetData &TD);
ASTContext &getContext() const { return Context; }
+ const LangOptions &getLangOptions() const { return Features; }
llvm::Module &getModule() const { return TheModule; }
CodeGenTypes &getTypes() { return Types; }
///
llvm::Function *getBuiltinLibFunction(unsigned BuiltinID);
llvm::Constant *GetAddrOfConstantCFString(const std::string& str);
+ llvm::Constant *GetAddrOfConstantString(const std::string& str);
llvm::Function *getMemCpyFn();
/// Init - Create an ModuleBuilder with the specified ASTContext.
clang::CodeGen::CodeGenModule *
-clang::CodeGen::Init(ASTContext &Context, llvm::Module &M,
- const llvm::TargetData &TD) {
- return new CodeGenModule(Context, M, TD);
+clang::CodeGen::Init(ASTContext &Context, const LangOptions &Features,
+ llvm::Module &M, const llvm::TargetData &TD) {
+ return new CodeGenModule(Context, Features, M, TD);
}
void clang::CodeGen::Terminate(CodeGenModule *B) {
llvm::Module *M;
const llvm::TargetData *TD;
ASTContext *Ctx;
+ const LangOptions &Features;
CodeGen::CodeGenModule *Builder;
public:
- LLVMEmitter(Diagnostic &diags) : Diags(diags) {}
+ LLVMEmitter(Diagnostic &diags, const LangOptions &LO)
+ : Diags(diags)
+ , Features(LO) {}
virtual void Initialize(ASTContext &Context, unsigned MainFileID) {
Ctx = &Context;
M = new llvm::Module("foo");
M->setTargetTriple(Ctx->Target.getTargetTriple());
TD = new llvm::TargetData(Ctx->Target.getTargetDescription());
- Builder = CodeGen::Init(Context, *M, *TD);
+ Builder = CodeGen::Init(Context, Features, *M, *TD);
}
virtual void HandleTopLevelDecl(Decl *D) {
};
} // end anonymous namespace
-ASTConsumer *clang::CreateLLVMEmitter(Diagnostic &Diags) {
- return new LLVMEmitter(Diags);
+ASTConsumer *clang::CreateLLVMEmitter(Diagnostic &Diags, const LangOptions &Features) {
+ return new LLVMEmitter(Diags, Features);
}
class ASTConsumer;
class Diagnostic;
+struct LangOptions;
ASTConsumer *CreateASTPrinter(FILE* FP = NULL);
ASTConsumer *CreateASTDumper();
ASTConsumer *CreateLiveVarAnalyzer();
ASTConsumer *CreateDeadStoreChecker(Diagnostic &Diags);
ASTConsumer *CreateUnitValsChecker(Diagnostic &Diags);
-ASTConsumer *CreateLLVMEmitter(Diagnostic &Diags);
+ASTConsumer *CreateLLVMEmitter(Diagnostic &Diags, const LangOptions &Features);
ASTConsumer *CreateCodeRewriterTest();
ASTConsumer *CreateSerializationTest();
PascalStrings("fpascal-strings",
llvm::cl::desc("Recognize and construct Pascal-style "
"string literals"));
+
+static llvm::cl::opt<bool>
+WritableStrings("fwritable-strings",
+ llvm::cl::desc("Store string literals as writable data."));
// FIXME: add:
// -ansi
// -trigraphs
Options.Trigraphs = 1; // -trigraphs or -ansi
Options.DollarIdents = 1; // FIXME: Really a target property.
Options.PascalStrings = PascalStrings;
+ Options.WritableStrings = WritableStrings;
}
//===----------------------------------------------------------------------===//
break;
case EmitLLVM:
- Consumer = CreateLLVMEmitter(PP.getDiagnostics());
+ Consumer = CreateLLVMEmitter(PP.getDiagnostics(), PP.getLangOptions());
break;
case RewriteTest:
unsigned PascalStrings : 1; // Allow Pascal strings
unsigned Boolean : 1; // Allow bool/true/false
+ unsigned WritableStrings : 1; // Allow writable strings
LangOptions() {
Trigraphs = BCPLComment = DollarIdents = Digraphs = HexFloats = 0;
ObjC1 = ObjC2 = 0;
C99 = Microsoft = CPlusPlus = CPlusPlus0x = NoExtensions = 0;
- CXXOperatorNames = PascalStrings = Boolean = 0;
+ CXXOperatorNames = PascalStrings = Boolean = WritableStrings = 0;
}
};
class ASTContext;
class FunctionDecl;
class FileVarDecl;
+ struct LangOptions;
namespace CodeGen {
class CodeGenModule;
/// Init - Create an ModuleBuilder with the specified ASTContext.
- CodeGenModule *Init(ASTContext &Context, llvm::Module &M,
- const llvm::TargetData &TD);
+ CodeGenModule *Init(ASTContext &Context, const LangOptions &Features,
+ llvm::Module &M, const llvm::TargetData &TD);
/// CodeGenFunction - Convert the AST node for a FunctionDecl into LLVM.
///