mirror of
https://github.com/intel/llvm.git
synced 2026-01-25 10:55:58 +08:00
Implement support for -fwritable-strings and make the code generator
merge string literals when it is not provided. llvm-svn: 44394
This commit is contained in:
@@ -304,18 +304,8 @@ LValue CodeGenFunction::EmitStringLiteralLValue(const StringLiteral *E) {
|
||||
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) {
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#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"
|
||||
@@ -24,9 +25,9 @@ using namespace clang;
|
||||
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) {
|
||||
@@ -155,27 +156,6 @@ static llvm::Constant *GenerateConstantCast(const Expr *Expression,
|
||||
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,
|
||||
@@ -244,7 +224,10 @@ static llvm::Constant *GenerateConstantExpr(const Expr* Expression,
|
||||
// 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.
|
||||
@@ -455,3 +438,39 @@ GetAddrOfConstantCFString(const std::string &str) {
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ namespace clang {
|
||||
class Decl;
|
||||
class ValueDecl;
|
||||
class FileVarDecl;
|
||||
struct LangOptions;
|
||||
|
||||
namespace CodeGen {
|
||||
|
||||
@@ -39,21 +40,25 @@ 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; }
|
||||
|
||||
@@ -64,6 +69,7 @@ public:
|
||||
///
|
||||
llvm::Function *getBuiltinLibFunction(unsigned BuiltinID);
|
||||
llvm::Constant *GetAddrOfConstantCFString(const std::string& str);
|
||||
llvm::Constant *GetAddrOfConstantString(const std::string& str);
|
||||
llvm::Function *getMemCpyFn();
|
||||
|
||||
|
||||
|
||||
@@ -18,9 +18,9 @@ using namespace clang;
|
||||
|
||||
/// 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) {
|
||||
|
||||
@@ -550,15 +550,18 @@ namespace {
|
||||
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) {
|
||||
@@ -588,7 +591,7 @@ namespace {
|
||||
};
|
||||
} // 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);
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ namespace clang {
|
||||
|
||||
class ASTConsumer;
|
||||
class Diagnostic;
|
||||
struct LangOptions;
|
||||
|
||||
ASTConsumer *CreateASTPrinter(FILE* FP = NULL);
|
||||
ASTConsumer *CreateASTDumper();
|
||||
@@ -28,7 +29,7 @@ ASTConsumer *CreateCFGDumper(bool ViewGraphs = false);
|
||||
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();
|
||||
|
||||
|
||||
@@ -278,6 +278,10 @@ static llvm::cl::opt<bool>
|
||||
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
|
||||
@@ -335,6 +339,7 @@ static void InitializeLanguageStandard(LangOptions &Options) {
|
||||
Options.Trigraphs = 1; // -trigraphs or -ansi
|
||||
Options.DollarIdents = 1; // FIXME: Really a target property.
|
||||
Options.PascalStrings = PascalStrings;
|
||||
Options.WritableStrings = WritableStrings;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
@@ -820,7 +825,7 @@ static void ProcessInputFile(Preprocessor &PP, unsigned MainFileID,
|
||||
break;
|
||||
|
||||
case EmitLLVM:
|
||||
Consumer = CreateLLVMEmitter(PP.getDiagnostics());
|
||||
Consumer = CreateLLVMEmitter(PP.getDiagnostics(), PP.getLangOptions());
|
||||
break;
|
||||
|
||||
case RewriteTest:
|
||||
|
||||
@@ -36,12 +36,13 @@ struct LangOptions {
|
||||
|
||||
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;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -23,13 +23,14 @@ namespace clang {
|
||||
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.
|
||||
///
|
||||
|
||||
Reference in New Issue
Block a user