Skip to content

Commit

Permalink
[CUDA] Allow parsing of host and device code simultaneously.
Browse files Browse the repository at this point in the history
 * adds -aux-triple option to specify target triple
 * propagates aux target info to AST context and Preprocessor
 * pulls in target specific preprocessor macros.
 * pulls in target-specific builtins from aux target.
 * sets appropriate host or device attribute on builtins.

Differential Revision: http://reviews.llvm.org/D12917

llvm-svn: 248299
  • Loading branch information
Artem-B committed Sep 22, 2015
1 parent ccf0d69 commit b5bc923
Show file tree
Hide file tree
Showing 15 changed files with 154 additions and 71 deletions.
11 changes: 7 additions & 4 deletions clang/include/clang/AST/ASTContext.h
Expand Up @@ -437,6 +437,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
friend class CXXRecordDecl;

const TargetInfo *Target;
const TargetInfo *AuxTarget;
clang::PrintingPolicy PrintingPolicy;

public:
Expand Down Expand Up @@ -523,7 +524,8 @@ class ASTContext : public RefCountedBase<ASTContext> {
}

const TargetInfo &getTargetInfo() const { return *Target; }

const TargetInfo *getAuxTargetInfo() const { return AuxTarget; }

/// getIntTypeForBitwidth -
/// sets integer QualTy according to specified details:
/// bitwidth, signed/unsigned.
Expand Down Expand Up @@ -2415,9 +2417,10 @@ class ASTContext : public RefCountedBase<ASTContext> {
/// This routine may only be invoked once for a given ASTContext object.
/// It is normally invoked after ASTContext construction.
///
/// \param Target The target
void InitBuiltinTypes(const TargetInfo &Target);

/// \param Target The target
void InitBuiltinTypes(const TargetInfo &Target,
const TargetInfo *AuxTarget = nullptr);

private:
void InitBuiltinType(CanQualType &R, BuiltinType::Kind K);

Expand Down
21 changes: 19 additions & 2 deletions clang/include/clang/Basic/Builtins.h
Expand Up @@ -56,15 +56,23 @@ struct Info {

/// \brief Holds information about both target-independent and
/// target-specific builtins, allowing easy queries by clients.
///
/// Builtins from an optional auxiliary target are stored in
/// AuxTSRecords. Their IDs are shifted up by NumTSRecords and need to
/// be translated back with getAuxBuiltinID() before use.
class Context {
const Info *TSRecords;
const Info *AuxTSRecords;
unsigned NumTSRecords;
unsigned NumAuxTSRecords;

public:
Context();

/// \brief Perform target-specific initialization
void initializeTarget(const TargetInfo &Target);

/// \param AuxTarget Target info to incorporate builtins from. May be nullptr.
void InitializeTarget(const TargetInfo &Target, const TargetInfo *AuxTarget);

/// \brief Mark the identifiers for all the builtins with their
/// appropriate builtin ID # and mark any non-portable builtin identifiers as
/// such.
Expand Down Expand Up @@ -176,6 +184,15 @@ class Context {
return getRecord(ID).Features;
}

/// \brief Return true if builtin ID belongs to AuxTarget.
bool isAuxBuiltinID(unsigned ID) const {
return ID >= (Builtin::FirstTSBuiltin + NumTSRecords);
}

/// Return real buitin ID (i.e. ID it would have furing compilation
/// for AuxTarget).
unsigned getAuxBuiltinID(unsigned ID) const { return ID - NumTSRecords; }

private:
const Info &getRecord(unsigned ID) const;

Expand Down
2 changes: 2 additions & 0 deletions clang/include/clang/Driver/CC1Options.td
Expand Up @@ -325,6 +325,8 @@ def cc1as : Flag<["-"], "cc1as">;
def ast_merge : Separate<["-"], "ast-merge">,
MetaVarName<"<ast file>">,
HelpText<"Merge the given AST file into the translation unit being compiled.">;
def aux_triple : Separate<["-"], "aux-triple">,
HelpText<"Auxiliary target triple.">;
def code_completion_at : Separate<["-"], "code-completion-at">,
MetaVarName<"<file>:<line>:<column>">,
HelpText<"Dump code-completion information at a location">;
Expand Down
12 changes: 12 additions & 0 deletions clang/include/clang/Frontend/CompilerInstance.h
Expand Up @@ -78,6 +78,9 @@ class CompilerInstance : public ModuleLoader {
/// The target being compiled for.
IntrusiveRefCntPtr<TargetInfo> Target;

/// Auxiliary Target info.
IntrusiveRefCntPtr<TargetInfo> AuxTarget;

/// The virtual file system.
IntrusiveRefCntPtr<vfs::FileSystem> VirtualFileSystem;

Expand Down Expand Up @@ -351,6 +354,15 @@ class CompilerInstance : public ModuleLoader {
/// Replace the current Target.
void setTarget(TargetInfo *Value);

/// }
/// @name AuxTarget Info
/// {

TargetInfo *getAuxTarget() const { return AuxTarget.get(); }

/// Replace the current AuxTarget.
void setAuxTarget(TargetInfo *Value);

/// }
/// @name Virtual File System
/// {
Expand Down
5 changes: 4 additions & 1 deletion clang/include/clang/Frontend/FrontendOptions.h
Expand Up @@ -256,7 +256,10 @@ class FrontendOptions {
/// \brief File name of the file that will provide record layouts
/// (in the format produced by -fdump-record-layouts).
std::string OverrideRecordLayoutsFile;


/// \brief Auxiliary triple for CUDA compilation.
std::string AuxTriple;

public:
FrontendOptions() :
DisableFree(false), RelocatablePCH(false), ShowHelp(false),
Expand Down
7 changes: 6 additions & 1 deletion clang/include/clang/Lex/Preprocessor.h
Expand Up @@ -98,6 +98,7 @@ class Preprocessor : public RefCountedBase<Preprocessor> {
DiagnosticsEngine *Diags;
LangOptions &LangOpts;
const TargetInfo *Target;
const TargetInfo *AuxTarget;
FileManager &FileMgr;
SourceManager &SourceMgr;
std::unique_ptr<ScratchBuffer> ScratchBuf;
Expand Down Expand Up @@ -656,7 +657,10 @@ class Preprocessor : public RefCountedBase<Preprocessor> {
///
/// \param Target is owned by the caller and must remain valid for the
/// lifetime of the preprocessor.
void Initialize(const TargetInfo &Target);
/// \param AuxTarget is owned by the caller and must remain valid for
/// the lifetime of the preprocessor.
void Initialize(const TargetInfo &Target,
const TargetInfo *AuxTarget = nullptr);

/// \brief Initialize the preprocessor to parse a model file
///
Expand All @@ -678,6 +682,7 @@ class Preprocessor : public RefCountedBase<Preprocessor> {

const LangOptions &getLangOpts() const { return LangOpts; }
const TargetInfo &getTargetInfo() const { return *Target; }
const TargetInfo *getAuxTargetInfo() const { return AuxTarget; }
FileManager &getFileManager() const { return FileMgr; }
SourceManager &getSourceManager() const { return SourceMgr; }
HeaderSearch &getHeaderSearchInfo() const { return HeaderInfo; }
Expand Down
14 changes: 8 additions & 6 deletions clang/lib/AST/ASTContext.cpp
Expand Up @@ -743,10 +743,10 @@ ASTContext::ASTContext(LangOptions &LOpts, SourceManager &SM,
FirstLocalImport(), LastLocalImport(), ExternCContext(nullptr),
SourceMgr(SM), LangOpts(LOpts),
SanitizerBL(new SanitizerBlacklist(LangOpts.SanitizerBlacklistFiles, SM)),
AddrSpaceMap(nullptr), Target(nullptr), PrintingPolicy(LOpts),
Idents(idents), Selectors(sels), BuiltinInfo(builtins),
DeclarationNames(*this), ExternalSource(nullptr), Listener(nullptr),
Comments(SM), CommentsLoaded(false),
AddrSpaceMap(nullptr), Target(nullptr), AuxTarget(nullptr),
PrintingPolicy(LOpts), Idents(idents), Selectors(sels),
BuiltinInfo(builtins), DeclarationNames(*this), ExternalSource(nullptr),
Listener(nullptr), Comments(SM), CommentsLoaded(false),
CommentCommandTraits(BumpAlloc, LOpts.CommentOpts), LastSDM(nullptr, 0) {
TUDecl = TranslationUnitDecl::Create(*this);
}
Expand Down Expand Up @@ -956,13 +956,15 @@ void ASTContext::InitBuiltinType(CanQualType &R, BuiltinType::Kind K) {
Types.push_back(Ty);
}

void ASTContext::InitBuiltinTypes(const TargetInfo &Target) {
void ASTContext::InitBuiltinTypes(const TargetInfo &Target,
const TargetInfo *AuxTarget) {
assert((!this->Target || this->Target == &Target) &&
"Incorrect target reinitialization");
assert(VoidTy.isNull() && "Context reinitialized?");

this->Target = &Target;

this->AuxTarget = AuxTarget;

ABI.reset(createCXXABI(Target));
AddrSpaceMap = getAddressSpaceMap(Target, LangOpts);
AddrSpaceMapMangling = isAddrSpaceMapManglingEnabled(Target, LangOpts);
Expand Down
19 changes: 16 additions & 3 deletions clang/lib/Basic/Builtins.cpp
Expand Up @@ -32,19 +32,27 @@ static const Builtin::Info BuiltinInfo[] = {
const Builtin::Info &Builtin::Context::getRecord(unsigned ID) const {
if (ID < Builtin::FirstTSBuiltin)
return BuiltinInfo[ID];
assert(ID - Builtin::FirstTSBuiltin < NumTSRecords && "Invalid builtin ID!");
assert(ID - Builtin::FirstTSBuiltin < (NumTSRecords + NumAuxTSRecords) &&
"Invalid builtin ID!");
if (isAuxBuiltinID(ID))
return AuxTSRecords[getAuxBuiltinID(ID) - Builtin::FirstTSBuiltin];
return TSRecords[ID - Builtin::FirstTSBuiltin];
}

Builtin::Context::Context() {
// Get the target specific builtins from the target.
TSRecords = nullptr;
AuxTSRecords = nullptr;
NumTSRecords = 0;
NumAuxTSRecords = 0;
}

void Builtin::Context::initializeTarget(const TargetInfo &Target) {
void Builtin::Context::InitializeTarget(const TargetInfo &Target,
const TargetInfo *AuxTarget) {
assert(NumTSRecords == 0 && "Already initialized target?");
Target.getTargetBuiltins(TSRecords, NumTSRecords);
if (AuxTarget)
AuxTarget->getTargetBuiltins(AuxTSRecords, NumAuxTSRecords);
}

bool Builtin::Context::builtinIsSupported(const Builtin::Info &BuiltinInfo,
Expand Down Expand Up @@ -76,7 +84,12 @@ void Builtin::Context::initializeBuiltins(IdentifierTable &Table,
// Step #2: Register target-specific builtins.
for (unsigned i = 0, e = NumTSRecords; i != e; ++i)
if (builtinIsSupported(TSRecords[i], LangOpts))
Table.get(TSRecords[i].Name).setBuiltinID(i+Builtin::FirstTSBuiltin);
Table.get(TSRecords[i].Name).setBuiltinID(i + Builtin::FirstTSBuiltin);

// Step #3: Register target-specific builtins for AuxTarget.
for (unsigned i = 0, e = NumAuxTSRecords; i != e; ++i)
Table.get(AuxTSRecords[i].Name)
.setBuiltinID(i + Builtin::FirstTSBuiltin + NumTSRecords);
}

void Builtin::Context::forgetBuiltin(unsigned ID, IdentifierTable &Table) {
Expand Down
36 changes: 25 additions & 11 deletions clang/lib/CodeGen/CGBuiltin.cpp
Expand Up @@ -1868,40 +1868,54 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
return GetUndefRValue(E->getType());
}

Value *CodeGenFunction::EmitTargetBuiltinExpr(unsigned BuiltinID,
const CallExpr *E) {
switch (getTarget().getTriple().getArch()) {
static Value *EmitTargetArchBuiltinExpr(CodeGenFunction *CGF,
unsigned BuiltinID, const CallExpr *E,
llvm::Triple::ArchType Arch) {
switch (Arch) {
case llvm::Triple::arm:
case llvm::Triple::armeb:
case llvm::Triple::thumb:
case llvm::Triple::thumbeb:
return EmitARMBuiltinExpr(BuiltinID, E);
return CGF->EmitARMBuiltinExpr(BuiltinID, E);
case llvm::Triple::aarch64:
case llvm::Triple::aarch64_be:
return EmitAArch64BuiltinExpr(BuiltinID, E);
return CGF->EmitAArch64BuiltinExpr(BuiltinID, E);
case llvm::Triple::x86:
case llvm::Triple::x86_64:
return EmitX86BuiltinExpr(BuiltinID, E);
return CGF->EmitX86BuiltinExpr(BuiltinID, E);
case llvm::Triple::ppc:
case llvm::Triple::ppc64:
case llvm::Triple::ppc64le:
return EmitPPCBuiltinExpr(BuiltinID, E);
return CGF->EmitPPCBuiltinExpr(BuiltinID, E);
case llvm::Triple::r600:
case llvm::Triple::amdgcn:
return EmitAMDGPUBuiltinExpr(BuiltinID, E);
return CGF->EmitAMDGPUBuiltinExpr(BuiltinID, E);
case llvm::Triple::systemz:
return EmitSystemZBuiltinExpr(BuiltinID, E);
return CGF->EmitSystemZBuiltinExpr(BuiltinID, E);
case llvm::Triple::nvptx:
case llvm::Triple::nvptx64:
return EmitNVPTXBuiltinExpr(BuiltinID, E);
return CGF->EmitNVPTXBuiltinExpr(BuiltinID, E);
case llvm::Triple::wasm32:
case llvm::Triple::wasm64:
return EmitWebAssemblyBuiltinExpr(BuiltinID, E);
return CGF->EmitWebAssemblyBuiltinExpr(BuiltinID, E);
default:
return nullptr;
}
}

Value *CodeGenFunction::EmitTargetBuiltinExpr(unsigned BuiltinID,
const CallExpr *E) {
if (getContext().BuiltinInfo.isAuxBuiltinID(BuiltinID)) {
assert(getContext().getAuxTargetInfo() && "Missing aux target info");
return EmitTargetArchBuiltinExpr(
this, getContext().BuiltinInfo.getAuxBuiltinID(BuiltinID), E,
getContext().getAuxTargetInfo()->getTriple().getArch());
}

return EmitTargetArchBuiltinExpr(this, BuiltinID, E,
getTarget().getTriple().getArch());
}

static llvm::VectorType *GetNeonType(CodeGenFunction *CGF,
NeonTypeFlags TypeFlags,
bool V1Ty=false) {
Expand Down
16 changes: 11 additions & 5 deletions clang/lib/Frontend/CompilerInstance.cpp
Expand Up @@ -78,9 +78,8 @@ void CompilerInstance::setDiagnostics(DiagnosticsEngine *Value) {
Diagnostics = Value;
}

void CompilerInstance::setTarget(TargetInfo *Value) {
Target = Value;
}
void CompilerInstance::setTarget(TargetInfo *Value) { Target = Value; }
void CompilerInstance::setAuxTarget(TargetInfo *Value) { AuxTarget = Value; }

void CompilerInstance::setFileManager(FileManager *Value) {
FileMgr = Value;
Expand Down Expand Up @@ -312,7 +311,7 @@ void CompilerInstance::createPreprocessor(TranslationUnitKind TUKind) {
PP = new Preprocessor(&getPreprocessorOpts(), getDiagnostics(), getLangOpts(),
getSourceManager(), *HeaderInfo, *this, PTHMgr,
/*OwnsHeaderSearch=*/true, TUKind);
PP->Initialize(getTarget());
PP->Initialize(getTarget(), getAuxTarget());

// Note that this is different then passing PTHMgr to Preprocessor's ctor.
// That argument is used as the IdentifierInfoLookup argument to
Expand Down Expand Up @@ -396,7 +395,7 @@ void CompilerInstance::createASTContext() {
auto *Context = new ASTContext(getLangOpts(), PP.getSourceManager(),
PP.getIdentifierTable(), PP.getSelectorTable(),
PP.getBuiltinInfo());
Context->InitBuiltinTypes(getTarget());
Context->InitBuiltinTypes(getTarget(), getAuxTarget());
setASTContext(Context);
}

Expand Down Expand Up @@ -800,6 +799,13 @@ bool CompilerInstance::ExecuteAction(FrontendAction &Act) {
if (!hasTarget())
return false;

// Create TargetInfo for the other side of CUDA compilation.
if (getLangOpts().CUDA && !getFrontendOpts().AuxTriple.empty()) {
std::shared_ptr<TargetOptions> TO(new TargetOptions);
TO->Triple = getFrontendOpts().AuxTriple;
setAuxTarget(TargetInfo::CreateTargetInfo(getDiagnostics(), TO));
}

// Inform the target of the language options.
//
// FIXME: We shouldn't need to do this, the target should be immutable once
Expand Down
3 changes: 3 additions & 0 deletions clang/lib/Frontend/CompilerInvocation.cpp
Expand Up @@ -975,6 +975,9 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,

Opts.OverrideRecordLayoutsFile
= Args.getLastArgValue(OPT_foverride_record_layout_EQ);
Opts.AuxTriple =
llvm::Triple::normalize(Args.getLastArgValue(OPT_aux_triple));

if (const Arg *A = Args.getLastArg(OPT_arcmt_check,
OPT_arcmt_modify,
OPT_arcmt_migrate)) {
Expand Down
4 changes: 4 additions & 0 deletions clang/lib/Frontend/InitPreprocessor.cpp
Expand Up @@ -918,6 +918,10 @@ void clang::InitializePreprocessor(

// Install things like __POWERPC__, __GNUC__, etc into the macro table.
if (InitOpts.UsePredefines) {
if (LangOpts.CUDA && PP.getAuxTargetInfo())
InitializePredefinedMacros(*PP.getAuxTargetInfo(), LangOpts, FEOpts,
Builder);

InitializePredefinedMacros(PP.getTargetInfo(), LangOpts, FEOpts, Builder);

// Install definitions to make Objective-C++ ARC work well with various
Expand Down

0 comments on commit b5bc923

Please sign in to comment.