- fix includes.
- WIP, committing stuff, splitting code motion.
- Merge branch 'pragma-comment-move' into pragma-comment
- fixes
http://llvm-reviews.chandlerc.com/D723
CHANGE SINCE LAST DIFF
http://llvm-reviews.chandlerc.com/D723?vs=1767&id=1850#toc
Files:
include/clang/AST/ASTConsumer.h
include/clang/Parse/Parser.h
include/clang/Sema/Sema.h
lib/CodeGen/CodeGenAction.cpp
lib/CodeGen/CodeGenModule.cpp
lib/CodeGen/CodeGenModule.h
lib/CodeGen/ModuleBuilder.cpp
lib/CodeGen/TargetInfo.cpp
lib/CodeGen/TargetInfo.h
lib/Lex/Lexer.cpp
lib/Parse/ParsePragma.cpp
lib/Parse/ParsePragma.h
lib/Parse/Parser.cpp
lib/Sema/SemaAttr.cpp
test/CodeGen/pragma-comment.c
test/Modules/autolink.m
Index: include/clang/AST/ASTConsumer.h
===================================================================
--- include/clang/AST/ASTConsumer.h
+++ include/clang/AST/ASTConsumer.h
@@ -14,6 +14,8 @@
#ifndef LLVM_CLANG_AST_ASTCONSUMER_H
#define LLVM_CLANG_AST_ASTCONSUMER_H
+#include "llvm/ADT/StringRef.h"
+
namespace clang {
class ASTContext;
class CXXRecordDecl;
@@ -86,6 +88,15 @@
/// The default implementation passes it to HandleTopLevelDecl.
virtual void HandleImplicitImportDecl(ImportDecl *D);
+ /// \brief Handle a pragma that appends to Linker Options. Currently this
+ /// only exists to support Microsoft's #pragma comment(linker, "/foo").
+ virtual void HandleLinkerOptionPragma(llvm::StringRef Opts) {}
+
+ /// \brief Handle a dependent library created by a pragma in the source.
+ /// Currently this only exists to support Microsoft's
+ /// #pragma comment(lib, "/foo").
+ virtual void HandleDependentLibrary(llvm::StringRef Lib) {}
+
/// CompleteTentativeDefinition - Callback invoked at the end of a translation
/// unit to notify the consumer that the given tentative definition should be
/// completed.
Index: include/clang/Parse/Parser.h
===================================================================
--- include/clang/Parse/Parser.h
+++ include/clang/Parse/Parser.h
@@ -419,6 +419,10 @@
void HandlePragmaMSStruct();
/// \brief Handle the annotation token produced for
+ /// #pragma comment...
+ void HandlePragmaMSComment();
+
+ /// \brief Handle the annotation token produced for
/// #pragma align...
void HandlePragmaAlign();
Index: include/clang/Sema/Sema.h
===================================================================
--- include/clang/Sema/Sema.h
+++ include/clang/Sema/Sema.h
@@ -49,6 +49,7 @@
#include "llvm/MC/MCParser/MCAsmParser.h"
#include <deque>
#include <string>
+#include <vector>
namespace llvm {
class APSInt;
@@ -6584,6 +6585,15 @@
PMSST_ON // #pragms ms_struct on
};
+ enum PragmaMSCommentKind {
+ PCK_Unknown,
+ PCK_Linker, // #pragma comment(linker, ...)
+ PCK_Lib, // #pragma comment(lib, ...)
+ PCK_Compiler, // #pragma comment(compiler, ...)
+ PCK_ExeStr, // #pragma comment(exestr, ...)
+ PCK_User // #pragma comment(user, ...)
+ };
+
/// ActOnPragmaPack - Called on well formed \#pragma pack(...).
void ActOnPragmaPack(PragmaPackKind Kind,
IdentifierInfo *Name,
@@ -6595,6 +6605,9 @@
/// ActOnPragmaMSStruct - Called on well formed \#pragma ms_struct [on|off].
void ActOnPragmaMSStruct(PragmaMSStructKind Kind);
+ /// ActOnPragmaMSStruct - Called on well formed \#pragma comment(kind, "arg").
+ void ActOnPragmaMSComment(PragmaMSCommentKind Kind, StringRef Arg);
+
/// ActOnPragmaUnused - Called on well-formed '\#pragma unused'.
void ActOnPragmaUnused(const Token &Identifier,
Scope *curScope,
Index: lib/CodeGen/CodeGenAction.cpp
===================================================================
--- lib/CodeGen/CodeGenAction.cpp
+++ lib/CodeGen/CodeGenAction.cpp
@@ -33,6 +33,7 @@
using namespace llvm;
namespace clang {
+
class BackendConsumer : public ASTConsumer {
virtual void anchor();
DiagnosticsEngine &Diags;
@@ -179,6 +180,14 @@
Gen->HandleVTable(RD, DefinitionRequired);
}
+ virtual void HandleLinkerOptionPragma(llvm::StringRef Opts) {
+ Gen->HandleLinkerOptionPragma(Opts);
+ }
+
+ virtual void HandleDependentLibrary(llvm::StringRef Opts) {
+ Gen->HandleDependentLibrary(Opts);
+ }
+
static void InlineAsmDiagHandler(const llvm::SMDiagnostic &SM,void *Context,
unsigned LocCookie) {
SourceLocation Loc = SourceLocation::getFromRawEncoding(LocCookie);
Index: lib/CodeGen/CodeGenModule.cpp
===================================================================
--- lib/CodeGen/CodeGenModule.cpp
+++ lib/CodeGen/CodeGenModule.cpp
@@ -186,7 +186,8 @@
EmitStaticExternCAliases();
EmitLLVMUsed();
- if (CodeGenOpts.Autolink && Context.getLangOpts().Modules) {
+ if (CodeGenOpts.Autolink &&
+ (Context.getLangOpts().Modules || !LinkerOptionsMetadata.empty())) {
EmitModuleLinkOptions();
}
@@ -762,31 +763,41 @@
GV->setSection("llvm.metadata");
}
+void CodeGenModule::AppendLinkerOptions(StringRef Opts) {
+ llvm::Value *MDOpts = llvm::MDString::get(getLLVMContext(), Opts);
+ LinkerOptionsMetadata.push_back(llvm::MDNode::get(getLLVMContext(), MDOpts));
+}
+
+void CodeGenModule::AddDependentLib(StringRef Lib) {
+ llvm::SmallString<24> Opt;
+ getTargetCodeGenInfo().getDependentLibraryOption(Lib, Opt);
+ llvm::Value *MDOpts = llvm::MDString::get(getLLVMContext(), Opt);
+ LinkerOptionsMetadata.push_back(llvm::MDNode::get(getLLVMContext(), MDOpts));
+}
+
/// \brief Add link options implied by the given module, including modules
/// it depends on, using a postorder walk.
-static void addLinkOptionsPostorder(llvm::LLVMContext &Context,
+static void addLinkOptionsPostorder(CodeGenModule &CGM,
Module *Mod,
SmallVectorImpl<llvm::Value *> &Metadata,
llvm::SmallPtrSet<Module *, 16> &Visited) {
// Import this module's parent.
if (Mod->Parent && Visited.insert(Mod->Parent)) {
- addLinkOptionsPostorder(Context, Mod->Parent, Metadata, Visited);
+ addLinkOptionsPostorder(CGM, Mod->Parent, Metadata, Visited);
}
// Import this module's dependencies.
for (unsigned I = Mod->Imports.size(); I > 0; --I) {
if (Visited.insert(Mod->Imports[I-1]))
- addLinkOptionsPostorder(Context, Mod->Imports[I-1], Metadata, Visited);
+ addLinkOptionsPostorder(CGM, Mod->Imports[I-1], Metadata, Visited);
}
// Add linker options to link against the libraries/frameworks
// described by this module.
+ llvm::LLVMContext &Context = CGM.getLLVMContext();
for (unsigned I = Mod->LinkLibraries.size(); I > 0; --I) {
- // FIXME: -lfoo is Unix-centric and -framework Foo is Darwin-centric.
- // We need to know more about the linker to know how to encode these
- // options propertly.
-
- // Link against a framework.
+ // Link against a framework. Frameworks are currently Darwin only, so we
+ // don't to ask TargetCodeGenInfo for the spelling of the linker option.
if (Mod->LinkLibraries[I-1].IsFramework) {
llvm::Value *Args[2] = {
llvm::MDString::get(Context, "-framework"),
@@ -798,9 +809,10 @@
}
// Link against a library.
- llvm::Value *OptString
- = llvm::MDString::get(Context,
- "-l" + Mod->LinkLibraries[I-1].Library);
+ llvm::SmallString<24> Opt;
+ CGM.getTargetCodeGenInfo().getDependentLibraryOption(
+ Mod->LinkLibraries[I-1].Library, Opt);
+ llvm::Value *OptString = llvm::MDString::get(Context, Opt);
Metadata.push_back(llvm::MDNode::get(Context, OptString));
}
}
@@ -852,20 +864,23 @@
}
// Add link options for all of the imported modules in reverse topological
- // order.
+ // order. We don't do anything to try to order import link flags with respect
+ // to linker options inserted by things like #pragma comment().
SmallVector<llvm::Value *, 16> MetadataArgs;
Visited.clear();
for (llvm::SetVector<clang::Module *>::iterator M = LinkModules.begin(),
MEnd = LinkModules.end();
M != MEnd; ++M) {
if (Visited.insert(*M))
- addLinkOptionsPostorder(getLLVMContext(), *M, MetadataArgs, Visited);
+ addLinkOptionsPostorder(*this, *M, MetadataArgs, Visited);
}
std::reverse(MetadataArgs.begin(), MetadataArgs.end());
+ LinkerOptionsMetadata.append(MetadataArgs.begin(), MetadataArgs.end());
// Add the linker options metadata flag.
getModule().addModuleFlag(llvm::Module::AppendUnique, "Linker Options",
- llvm::MDNode::get(getLLVMContext(), MetadataArgs));
+ llvm::MDNode::get(getLLVMContext(),
+ LinkerOptionsMetadata));
}
void CodeGenModule::EmitDeferred() {
Index: lib/CodeGen/CodeGenModule.h
===================================================================
--- lib/CodeGen/CodeGenModule.h
+++ lib/CodeGen/CodeGenModule.h
@@ -355,6 +355,9 @@
/// \brief The complete set of modules that has been imported.
llvm::SetVector<clang::Module *> ImportedModules;
+ /// \brief A vector of metadata strings.
+ SmallVector<llvm::Value *, 16> LinkerOptionsMetadata;
+
/// @name Cache for Objective-C runtime types
/// @{
@@ -906,6 +909,12 @@
void EmitVTable(CXXRecordDecl *Class, bool DefinitionRequired);
+ /// \brief Appends Opts to the "Linker Options" metadata value.
+ void AppendLinkerOptions(StringRef Opts);
+
+ /// \brief Appends a dependent lib to the "Linker Options" metadata value.
+ void AddDependentLib(StringRef Lib);
+
llvm::GlobalVariable::LinkageTypes
getFunctionLinkage(const FunctionDecl *FD);
Index: lib/CodeGen/ModuleBuilder.cpp
===================================================================
--- lib/CodeGen/ModuleBuilder.cpp
+++ lib/CodeGen/ModuleBuilder.cpp
@@ -20,6 +20,7 @@
#include "clang/Basic/TargetInfo.h"
#include "clang/Frontend/CodeGenOptions.h"
#include "llvm/ADT/OwningPtr.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
@@ -115,6 +116,15 @@
Builder->EmitVTable(RD, DefinitionRequired);
}
+
+ virtual void HandleLinkerOptionPragma(llvm::StringRef Opts) {
+ Builder->AppendLinkerOptions(Opts);
+ }
+
+ virtual void HandleDependentLibrary(llvm::StringRef Lib) {
+ Builder->AddDependentLib(Lib);
+ }
+
};
}
Index: lib/CodeGen/TargetInfo.cpp
===================================================================
--- lib/CodeGen/TargetInfo.cpp
+++ lib/CodeGen/TargetInfo.cpp
@@ -143,6 +143,16 @@
return false;
}
+void
+TargetCodeGenInfo::getDependentLibraryOption(llvm::StringRef Lib,
+ llvm::SmallString<24> &Opt) const {
+ // This assumes the user is passing a library name like "rt" instead of a
+ // filename like "librt.a/so", and that they don't care whether it's static or
+ // dynamic.
+ Opt = "-l";
+ Opt += Lib;
+}
+
static bool isEmptyRecord(ASTContext &Context, QualType T, bool AllowArrays);
/// isEmptyField - Return true iff a the field is "empty", that is it
@@ -1256,6 +1266,18 @@
};
+class WinX86_32TargetCodeGenInfo : public X86_32TargetCodeGenInfo {
+public:
+ WinX86_32TargetCodeGenInfo(CodeGen::CodeGenTypes &CGT, unsigned RegParms)
+ : X86_32TargetCodeGenInfo(CGT, false, true, true, RegParms) {}
+
+ void getDependentLibraryOption(llvm::StringRef Lib,
+ llvm::SmallString<24> &Opt) const {
+ Opt = "/DEFAULTLIB:";
+ Opt += Lib;
+ }
+};
+
class WinX86_64TargetCodeGenInfo : public TargetCodeGenInfo {
public:
WinX86_64TargetCodeGenInfo(CodeGen::CodeGenTypes &CGT)
@@ -1274,6 +1296,12 @@
AssignToArrayRange(CGF.Builder, Address, Eight8, 0, 16);
return false;
}
+
+ void getDependentLibraryOption(llvm::StringRef Lib,
+ llvm::SmallString<24> &Opt) const {
+ Opt = "/DEFAULTLIB:";
+ Opt += Lib;
+ }
};
}
@@ -5173,8 +5201,8 @@
case llvm::Triple::Win32:
return *(TheTargetCodeGenInfo =
- new X86_32TargetCodeGenInfo(Types, false, true, true,
- CodeGenOpts.NumRegisterParameters));
+ new WinX86_32TargetCodeGenInfo(Types,
+ CodeGenOpts.NumRegisterParameters));
default:
return *(TheTargetCodeGenInfo =
Index: lib/CodeGen/TargetInfo.h
===================================================================
--- lib/CodeGen/TargetInfo.h
+++ lib/CodeGen/TargetInfo.h
@@ -18,6 +18,7 @@
#include "clang/AST/Type.h"
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/SmallString.h"
namespace llvm {
class GlobalValue;
@@ -167,6 +168,11 @@
/// that unprototyped calls to varargs functions still succeed.
virtual bool isNoProtoCallVariadic(const CodeGen::CallArgList &args,
const FunctionNoProtoType *fnType) const;
+
+ /// Gets the linker options necessary to link a dependent library on this
+ /// platform.
+ virtual void getDependentLibraryOption(llvm::StringRef Lib,
+ llvm::SmallString<24> &Opt) const;
};
}
Index: lib/Lex/Lexer.cpp
===================================================================
--- lib/Lex/Lexer.cpp
+++ lib/Lex/Lexer.cpp
@@ -339,6 +339,16 @@
/// UCNs, etc.
std::string Lexer::getSpelling(const Token &Tok, const SourceManager &SourceMgr,
const LangOptions &LangOpts, bool *Invalid) {
+ std::string Result;
+ // Annotations generated by the lexer don't have spellings or lengths.
+ // Usually they're storing integer data, so dump that.
+ if (Tok.isAnnotation()) {
+ llvm::raw_string_ostream os(Result);
+ os << reinterpret_cast<uintptr_t>(Tok.getAnnotationValue());
+ os.flush();
+ return Result;
+ }
+
assert((int)Tok.getLength() >= 0 && "Token character range is bogus!");
bool CharDataInvalid = false;
@@ -353,7 +363,6 @@
if (!Tok.needsCleaning())
return std::string(TokStart, TokStart + Tok.getLength());
- std::string Result;
Result.resize(Tok.getLength());
Result.resize(getSpellingSlow(Tok, TokStart, LangOpts, &*Result.begin()));
return Result;
Index: lib/Parse/ParsePragma.cpp
===================================================================
--- lib/Parse/ParsePragma.cpp
+++ lib/Parse/ParsePragma.cpp
@@ -821,10 +821,16 @@
}
// Verify that this is one of the 5 whitelisted options.
- // FIXME: warn that 'exestr' is deprecated.
- const IdentifierInfo *II = Tok.getIdentifierInfo();
- if (!II->isStr("compiler") && !II->isStr("exestr") && !II->isStr("lib") &&
- !II->isStr("linker") && !II->isStr("user")) {
+ IdentifierInfo *II = Tok.getIdentifierInfo();
+ Sema::PragmaMSCommentKind Kind =
+ llvm::StringSwitch<Sema::PragmaMSCommentKind>(II->getName())
+ .Case("linker", Sema::PCK_Linker)
+ .Case("lib", Sema::PCK_Lib)
+ .Case("compiler", Sema::PCK_Compiler)
+ .Case("exestr", Sema::PCK_ExeStr)
+ .Case("user", Sema::PCK_User)
+ .Default(Sema::PCK_Unknown);
+ if (Kind == Sema::PCK_Unknown) {
PP.Diag(Tok.getLocation(), diag::err_pragma_comment_unknown_kind);
return;
}
@@ -837,11 +843,12 @@
/*MacroExpansion=*/true))
return;
+ // FIXME: warn that 'exestr' is deprecated.
// FIXME: If the kind is "compiler" warn if the string is present (it is
// ignored).
- // FIXME: 'lib' requires a comment string.
- // FIXME: 'linker' requires a comment string, and has a specific list of
- // things that are allowable.
+ // The MSDN docs say that "lib" and "linker" require a string and have a short
+ // whitelist of linker options they support, but in practice MSVC doesn't
+ // issue a diagnostic. Therefore neither does clang.
if (Tok.isNot(tok::r_paren)) {
PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed);
@@ -857,4 +864,6 @@
// If the pragma is lexically sound, notify any interested PPCallbacks.
if (PP.getPPCallbacks())
PP.getPPCallbacks()->PragmaComment(CommentLoc, II, ArgumentString);
+
+ Actions.ActOnPragmaMSComment(Kind, ArgumentString);
}
Index: lib/Parse/ParsePragma.h
===================================================================
--- lib/Parse/ParsePragma.h
+++ lib/Parse/ParsePragma.h
@@ -116,9 +116,12 @@
/// PragmaCommentHandler - "\#pragma comment ...".
class PragmaCommentHandler : public PragmaHandler {
public:
- PragmaCommentHandler() : PragmaHandler("comment") {}
+ PragmaCommentHandler(Sema &Actions)
+ : PragmaHandler("comment"), Actions(Actions) {}
virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
Token &FirstToken);
+private:
+ Sema &Actions;
};
} // end namespace clang
Index: lib/Parse/Parser.cpp
===================================================================
--- lib/Parse/Parser.cpp
+++ lib/Parse/Parser.cpp
@@ -103,7 +103,7 @@
PP.AddPragmaHandler(OpenMPHandler.get());
if (getLangOpts().MicrosoftExt) {
- MSCommentHandler.reset(new PragmaCommentHandler());
+ MSCommentHandler.reset(new PragmaCommentHandler(actions));
PP.AddPragmaHandler(MSCommentHandler.get());
}
Index: lib/Sema/SemaAttr.cpp
===================================================================
--- lib/Sema/SemaAttr.cpp
+++ lib/Sema/SemaAttr.cpp
@@ -13,6 +13,7 @@
//===----------------------------------------------------------------------===//
#include "clang/Sema/SemaInternal.h"
+#include "clang/AST/ASTConsumer.h"
#include "clang/AST/Attr.h"
#include "clang/AST/Expr.h"
#include "clang/Basic/TargetInfo.h"
@@ -263,6 +264,26 @@
MSStructPragmaOn = (Kind == PMSST_ON);
}
+void Sema::ActOnPragmaMSComment(PragmaMSCommentKind Kind, llvm::StringRef Arg) {
+ // FIXME: Serialize this.
+ switch (Kind) {
+ case PCK_Unknown:
+ llvm_unreachable("unexpected pragma comment kind");
+ case PCK_Linker:
+ Consumer.HandleLinkerOptionPragma(Arg);
+ return;
+ case PCK_Lib: {
+ Consumer.HandleDependentLibrary(Arg);
+ return;
+ }
+ case PCK_Compiler:
+ case PCK_ExeStr:
+ case PCK_User:
+ return; // We ignore all of these.
+ }
+ llvm_unreachable("invalid pragma comment kind");
+}
+
void Sema::ActOnPragmaUnused(const Token &IdTok, Scope *curScope,
SourceLocation PragmaLoc) {
Index: test/CodeGen/pragma-comment.c
===================================================================
--- /dev/null
+++ test/CodeGen/pragma-comment.c
@@ -0,0 +1,17 @@
+// RUN: %clang_cc1 %s -triple i686-pc-win32 -fms-extensions -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 %s -triple x86_64-pc-win32 -fms-extensions -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 %s -triple i686-pc-linux -fms-extensions -emit-llvm -o - | FileCheck -check-prefix LINUX %s
+
+#pragma comment(lib, "msvcrt.lib")
+
+#define BAR "2"
+#pragma comment(linker," /bar=" BAR)
+
+// CHECK: !llvm.module.flags = !{!0}
+// CHECK: !0 = metadata !{i32 6, metadata !"Linker Options", metadata ![[link_opts:[0-9]+]]}
+// CHECK: ![[link_opts]] = metadata !{metadata ![[msvcrt:[0-9]+]], metadata ![[bar:[0-9]+]]}
+// CHECK: ![[msvcrt]] = metadata !{metadata !"/DEFAULTLIB:msvcrt.lib"}
+// CHECK: ![[bar]] = metadata !{metadata !" /bar=2"}
+
+// LINUX: metadata !{metadata !"-lmsvcrt.lib"}
+// LINUX: metadata !{metadata !" /bar=2"}
Index: test/Modules/autolink.m
===================================================================
--- test/Modules/autolink.m
+++ test/Modules/autolink.m
@@ -35,7 +35,7 @@
// CHECK: !4 = metadata !{i32 6, metadata !"Linker Options", metadata ![[AUTOLINK_OPTIONS:[0-9]+]]}
// CHECK: ![[AUTOLINK_OPTIONS]] = metadata !{metadata ![[AUTOLINK_FRAMEWORK:[0-9]+]], metadata ![[AUTOLINK:[0-9]+]], metadata ![[DEPENDSONMODULE:[0-9]+]], metadata ![[MODULE:[0-9]+]], metadata ![[NOUMBRELLA:[0-9]+]]}
// CHECK: ![[AUTOLINK_FRAMEWORK]] = metadata !{metadata !"-framework", metadata !"autolink_framework"}
-// CHECK: ![[AUTOLINK]] = metadata !{metadata !"-lautolink"}
+// CHECK: ![[AUTOLINK]] = metadata !{metadata !"{{(-l|/DEFAULTLIB:)}}autolink"}
// CHECK: ![[DEPENDSONMODULE]] = metadata !{metadata !"-framework", metadata !"DependsOnModule"}
// CHECK: ![[MODULE]] = metadata !{metadata !"-framework", metadata !"Module"}
// CHECK: ![[NOUMBRELLA]] = metadata !{metadata !"-framework", metadata !"NoUmbrella"}
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits