diff options
author | Nico Weber <nicolasweber@gmx.de> | 2012-06-23 02:07:59 +0000 |
---|---|---|
committer | Nico Weber <nicolasweber@gmx.de> | 2012-06-23 02:07:59 +0000 |
commit | 28ad063b279378b19cb0704f977429df366a151e (patch) | |
tree | 4c797a94b4a042caaad08b236cca4b314c92be6e /lib/CodeGen | |
parent | 3f835687b8f7ad3060fe4c462727b212ed714b30 (diff) |
Support L__FUNCTION__ in microsoft mode, PR11789
Heavily based on a patch from
Aaron Wishnick <aaron.s.wishnick@gmail.com>.
I'll clean up the duplicated function in CodeGen as
a follow-up, later today or tomorrow.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@159060 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen')
-rw-r--r-- | lib/CodeGen/CGExpr.cpp | 101 |
1 files changed, 95 insertions, 6 deletions
diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index 0f794487b9..c8563d6044 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/lib/CodeGen/CGExpr.cpp @@ -21,6 +21,7 @@ #include "TargetInfo.h" #include "clang/AST/ASTContext.h" #include "clang/AST/DeclObjC.h" +#include "clang/Basic/ConvertUTF.h" #include "clang/Frontend/CodeGenOptions.h" #include "llvm/Intrinsics.h" #include "llvm/LLVMContext.h" @@ -1701,6 +1702,73 @@ LValue CodeGenFunction::EmitObjCEncodeExprLValue(const ObjCEncodeExpr *E) { E->getType()); } +static llvm::Constant* +GetAddrOfConstantWideString(StringRef Str, + const char *GlobalName, + ASTContext &Context, + QualType Ty, SourceLocation Loc, + CodeGenModule &CGM) { + + StringLiteral *SL = StringLiteral::Create(Context, + Str, + StringLiteral::Wide, + /*Pascal = */false, + Ty, Loc); + llvm::Constant *C = CGM.GetConstantArrayFromStringLiteral(SL); + llvm::GlobalVariable *GV = + new llvm::GlobalVariable(CGM.getModule(), C->getType(), + !CGM.getLangOpts().WritableStrings, + llvm::GlobalValue::PrivateLinkage, + C, GlobalName); + const unsigned WideAlignment = + Context.getTypeAlignInChars(Ty).getQuantity(); + GV->setAlignment(WideAlignment); + return GV; +} + +// FIXME: Mostly copied from StringLiteralParser::CopyStringFragment +static void ConvertUTF8ToWideString(unsigned CharByteWidth, StringRef Source, + SmallString<32>& Target) { + Target.resize(CharByteWidth * (Source.size() + 1)); + char* ResultPtr = &Target[0]; + + assert(CharByteWidth==1 || CharByteWidth==2 || CharByteWidth==4); + ConversionResult result = conversionOK; + // Copy the character span over. + if (CharByteWidth == 1) { + if (!isLegalUTF8String(reinterpret_cast<const UTF8*>(&*Source.begin()), + reinterpret_cast<const UTF8*>(&*Source.end()))) + result = sourceIllegal; + memcpy(ResultPtr, Source.data(), Source.size()); + ResultPtr += Source.size(); + } else if (CharByteWidth == 2) { + UTF8 const *sourceStart = (UTF8 const *)Source.data(); + // FIXME: Make the type of the result buffer correct instead of + // using reinterpret_cast. + UTF16 *targetStart = reinterpret_cast<UTF16*>(ResultPtr); + ConversionFlags flags = strictConversion; + result = ConvertUTF8toUTF16( + &sourceStart,sourceStart + Source.size(), + &targetStart,targetStart + 2*Source.size(),flags); + if (result==conversionOK) + ResultPtr = reinterpret_cast<char*>(targetStart); + } else if (CharByteWidth == 4) { + UTF8 const *sourceStart = (UTF8 const *)Source.data(); + // FIXME: Make the type of the result buffer correct instead of + // using reinterpret_cast. + UTF32 *targetStart = reinterpret_cast<UTF32*>(ResultPtr); + ConversionFlags flags = strictConversion; + result = ConvertUTF8toUTF32( + &sourceStart,sourceStart + Source.size(), + &targetStart,targetStart + 4*Source.size(),flags); + if (result==conversionOK) + ResultPtr = reinterpret_cast<char*>(targetStart); + } + assert((result != targetExhausted) + && "ConvertUTF8toUTFXX exhausted target buffer"); + assert(result == conversionOK); + Target.resize(ResultPtr - &Target[0]); +} LValue CodeGenFunction::EmitPredefinedLValue(const PredefinedExpr *E) { switch (E->getIdentType()) { @@ -1709,11 +1777,12 @@ LValue CodeGenFunction::EmitPredefinedLValue(const PredefinedExpr *E) { case PredefinedExpr::Func: case PredefinedExpr::Function: + case PredefinedExpr::LFunction: case PredefinedExpr::PrettyFunction: { - unsigned Type = E->getIdentType(); + unsigned IdentType = E->getIdentType(); std::string GlobalVarName; - switch (Type) { + switch (IdentType) { default: llvm_unreachable("Invalid type"); case PredefinedExpr::Func: GlobalVarName = "__func__."; @@ -1721,6 +1790,9 @@ LValue CodeGenFunction::EmitPredefinedLValue(const PredefinedExpr *E) { case PredefinedExpr::Function: GlobalVarName = "__FUNCTION__."; break; + case PredefinedExpr::LFunction: + GlobalVarName = "L__FUNCTION__."; + break; case PredefinedExpr::PrettyFunction: GlobalVarName = "__PRETTY_FUNCTION__."; break; @@ -1738,10 +1810,27 @@ LValue CodeGenFunction::EmitPredefinedLValue(const PredefinedExpr *E) { std::string FunctionName = (isa<BlockDecl>(CurDecl) ? FnName.str() - : PredefinedExpr::ComputeName((PredefinedExpr::IdentType)Type, CurDecl)); - - llvm::Constant *C = - CGM.GetAddrOfConstantCString(FunctionName, GlobalVarName.c_str()); + : PredefinedExpr::ComputeName((PredefinedExpr::IdentType)IdentType, + CurDecl)); + + const Type* ElemType = E->getType()->getArrayElementTypeNoTypeQual(); + llvm::Constant *C; + if (ElemType->isWideCharType()) { + SmallString<32> RawChars; + ConvertUTF8ToWideString( + getContext().getTypeSizeInChars(ElemType).getQuantity(), + FunctionName, RawChars); + C = GetAddrOfConstantWideString(RawChars, + GlobalVarName.c_str(), + getContext(), + E->getType(), + E->getLocation(), + CGM); + } else { + C = CGM.GetAddrOfConstantCString(FunctionName, + GlobalVarName.c_str(), + 1); + } return MakeAddrLValue(C, E->getType()); } } |