Skip to content

Commit dedfc35

Browse files
author
Erich Keane
authored
[SYCL] Add infrastructure for integration footer (#3455)
We need a separate header that the driver will insert at the end of host translation unit to support SYCL 2020 spec-constants and is_device_copyable (plus potentially more in the future). This patch puts the infrastructure together so that these things can be added when final specifications are available, and so that the driver can implement their component.
1 parent d513074 commit dedfc35

File tree

7 files changed

+99
-27
lines changed

7 files changed

+99
-27
lines changed

clang/include/clang/Basic/LangOptions.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,9 @@ class LangOptions : public LangOptionsBase {
350350
/// SYCL integration header to be generated by the device compiler
351351
std::string SYCLIntHeader;
352352

353+
/// SYCL integration footer to be generated by the device compiler
354+
std::string SYCLIntFooter;
355+
353356
LangOptions();
354357

355358
// Define accessors/mutators for language options of enumeration type.

clang/include/clang/Driver/Options.td

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5685,6 +5685,11 @@ def fsycl_int_header : Separate<["-"], "fsycl-int-header">,
56855685
MarshallingInfoString<LangOpts<"SYCLIntHeader">>;
56865686
def fsycl_int_header_EQ : Joined<["-"], "fsycl-int-header=">,
56875687
Alias<fsycl_int_header>;
5688+
def fsycl_int_footer : Separate<["-"], "fsycl-int-footer">,
5689+
HelpText<"Generate SYCL integration footer into this file.">,
5690+
MarshallingInfoString<LangOpts<"SYCLIntFooter">>;
5691+
def fsycl_int_footer_EQ : Joined<["-"], "fsycl-int-footer=">,
5692+
Alias<fsycl_int_footer>;
56885693
def fsycl_std_layout_kernel_params: Flag<["-"], "fsycl-std-layout-kernel-params">,
56895694
HelpText<"Enable standard layout requirement for SYCL kernel parameters.">,
56905695
MarshallingInfoFlag<LangOpts<"SYCLStdLayoutKernelParams">>;

clang/include/clang/Sema/Sema.h

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -320,15 +320,14 @@ class SYCLIntegrationHeader {
320320
};
321321

322322
public:
323-
SYCLIntegrationHeader(DiagnosticsEngine &Diag, bool UnnamedLambdaSupport,
324-
Sema &S);
323+
SYCLIntegrationHeader(bool UnnamedLambdaSupport, Sema &S);
325324

326325
/// Emits contents of the header into given stream.
327326
void emit(raw_ostream &Out);
328327

329328
/// Emits contents of the header into a file with given name.
330329
/// Returns true/false on success/failure.
331-
bool emit(const StringRef &MainSrc);
330+
bool emit(StringRef MainSrc);
332331

333332
/// Signals that subsequent parameter descriptor additions will go to
334333
/// the kernel with given name. Starts new kernel invocation descriptor.
@@ -431,6 +430,16 @@ class SYCLIntegrationHeader {
431430
Sema &S;
432431
};
433432

433+
class SYCLIntegrationFooter {
434+
public:
435+
SYCLIntegrationFooter(Sema &S) : S(S) {}
436+
bool emit(StringRef MainSrc);
437+
438+
private:
439+
bool emit(raw_ostream &O);
440+
Sema &S;
441+
};
442+
434443
/// Tracks expected type during expression parsing, for use in code completion.
435444
/// The type is tied to a particular token, all functions that update or consume
436445
/// the type take a start location of the token they are looking at as a
@@ -13119,6 +13128,7 @@ class Sema final {
1311913128
// SYCL integration header instance for current compilation unit this Sema
1312013129
// is associated with.
1312113130
std::unique_ptr<SYCLIntegrationHeader> SyclIntHeader;
13131+
std::unique_ptr<SYCLIntegrationFooter> SyclIntFooter;
1312213132

1312313133
// Used to suppress diagnostics during kernel construction, since these were
1312413134
// already emitted earlier. Diagnosing during Kernel emissions also skips the
@@ -13133,10 +13143,16 @@ class Sema final {
1313313143
SYCLIntegrationHeader &getSyclIntegrationHeader() {
1313413144
if (SyclIntHeader == nullptr)
1313513145
SyclIntHeader = std::make_unique<SYCLIntegrationHeader>(
13136-
getDiagnostics(), getLangOpts().SYCLUnnamedLambda, *this);
13146+
getLangOpts().SYCLUnnamedLambda, *this);
1313713147
return *SyclIntHeader.get();
1313813148
}
1313913149

13150+
SYCLIntegrationFooter &getSyclIntegrationFooter() {
13151+
if (SyclIntFooter == nullptr)
13152+
SyclIntFooter = std::make_unique<SYCLIntegrationFooter>(*this);
13153+
return *SyclIntFooter.get();
13154+
}
13155+
1314013156
enum SYCLRestrictKind {
1314113157
KernelGlobalVariable,
1314213158
KernelRTTI,

clang/lib/Frontend/CompilerInvocation.cpp

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3698,8 +3698,8 @@ bool CompilerInvocation::ParseLangArgs(LangOptions &Opts, ArgList &Args,
36983698
// '-mignore-xcoff-visibility' is implied. The generated command line will
36993699
// contain both '-fvisibility default' and '-mignore-xcoff-visibility' and
37003700
// subsequent calls to `CreateFromArgs`/`generateCC1CommandLine` will always
3701-
// produce the same arguments.
3702-
3701+
// produce the same arguments.
3702+
37033703
if (T.isOSAIX() && (Args.hasArg(OPT_mignore_xcoff_visibility) ||
37043704
!Args.hasArg(OPT_fvisibility)))
37053705
Opts.IgnoreXCOFFVisibility = 1;
@@ -4291,6 +4291,22 @@ static bool ParseTargetArgs(TargetOptions &Opts, ArgList &Args,
42914291
return Success && Diags.getNumErrors() == NumErrorsBefore;
42924292
}
42934293

4294+
static void CreateEmptyFile(StringRef HeaderName) {
4295+
if (HeaderName.empty())
4296+
return;
4297+
4298+
Expected<llvm::sys::fs::file_t> FT = llvm::sys::fs::openNativeFileForWrite(
4299+
HeaderName, llvm::sys::fs::CD_OpenAlways, llvm::sys::fs::OF_None);
4300+
if (FT)
4301+
llvm::sys::fs::closeFile(*FT);
4302+
else {
4303+
// Emit a message but don't terminate; compilation will fail
4304+
// later if this file is absent.
4305+
llvm::errs() << "Error: " << llvm::toString(FT.takeError())
4306+
<< " when opening " << HeaderName << "\n";
4307+
}
4308+
}
4309+
42944310
bool CompilerInvocation::CreateFromArgsImpl(
42954311
CompilerInvocation &Res, ArrayRef<const char *> CommandLineArgs,
42964312
DiagnosticsEngine &Diags, const char *Argv0) {
@@ -4372,21 +4388,9 @@ bool CompilerInvocation::CreateFromArgsImpl(
43724388
if (LangOpts.SYCLIsDevice) {
43734389
// Set the triple of the host for SYCL device compile.
43744390
Res.getTargetOpts().HostTriple = Res.getFrontendOpts().AuxTriple;
4375-
// If specified, create an empty integration header file for now.
4376-
const StringRef &HeaderName = LangOpts.SYCLIntHeader;
4377-
if (!HeaderName.empty()) {
4378-
Expected<llvm::sys::fs::file_t> ft =
4379-
llvm::sys::fs::openNativeFileForWrite(
4380-
HeaderName, llvm::sys::fs::CD_OpenAlways, llvm::sys::fs::OF_None);
4381-
if (ft)
4382-
llvm::sys::fs::closeFile(*ft);
4383-
else {
4384-
// Emit a message but don't terminate; compilation will fail
4385-
// later if this file is absent.
4386-
llvm::errs() << "Error: " << llvm::toString(ft.takeError())
4387-
<< " when opening " << HeaderName << "\n";
4388-
}
4389-
}
4391+
// If specified, create empty integration header files for now.
4392+
CreateEmptyFile(LangOpts.SYCLIntHeader);
4393+
CreateEmptyFile(LangOpts.SYCLIntFooter);
43904394
}
43914395

43924396
Success &= ParseCodeGenArgs(Res.getCodeGenOpts(), Args, DashX, Diags, T,

clang/lib/Sema/Sema.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
183183
DisableTypoCorrection(false), TyposCorrected(0), AnalysisWarnings(*this),
184184
ThreadSafetyDeclCache(nullptr), VarDataSharingAttributesStack(nullptr),
185185
CurScope(nullptr), Ident_super(nullptr), Ident___float128(nullptr),
186-
SyclIntHeader(nullptr) {
186+
SyclIntHeader(nullptr), SyclIntFooter(nullptr) {
187187
TUScope = nullptr;
188188
isConstantEvaluatedOverride = false;
189189

@@ -1037,6 +1037,8 @@ void Sema::ActOnEndOfTranslationUnitFragment(TUFragmentKind Kind) {
10371037
// Emit SYCL integration header for current translation unit if needed
10381038
if (SyclIntHeader != nullptr)
10391039
SyclIntHeader->emit(getLangOpts().SYCLIntHeader);
1040+
if (SyclIntFooter != nullptr)
1041+
SyclIntFooter->emit(getLangOpts().SYCLIntFooter);
10401042
MarkDevice();
10411043
}
10421044

clang/lib/Sema/SemaSYCL.cpp

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3093,6 +3093,14 @@ class SyclKernelIntHeaderCreator : public SyclKernelFieldHandler {
30933093
using SyclKernelFieldHandler::leaveStruct;
30943094
};
30953095

3096+
class SyclKernelIntFooterCreator : public SyclKernelFieldHandler {
3097+
SYCLIntegrationFooter &Footer;
3098+
3099+
public:
3100+
SyclKernelIntFooterCreator(Sema &S, SYCLIntegrationFooter &F)
3101+
: SyclKernelFieldHandler(S), Footer(F) {}
3102+
};
3103+
30963104
} // namespace
30973105

30983106
class SYCLKernelNameTypeVisitor
@@ -3418,9 +3426,13 @@ void Sema::ConstructOpenCLKernel(FunctionDecl *KernelCallerFunc,
34183426
calculateKernelNameType(Context, KernelCallerFunc), KernelName,
34193427
StableName, KernelCallerFunc);
34203428

3429+
SyclKernelIntFooterCreator int_footer(*this, getSyclIntegrationFooter());
3430+
34213431
KernelObjVisitor Visitor{*this};
3422-
Visitor.VisitRecordBases(KernelObj, kernel_decl, kernel_body, int_header);
3423-
Visitor.VisitRecordFields(KernelObj, kernel_decl, kernel_body, int_header);
3432+
Visitor.VisitRecordBases(KernelObj, kernel_decl, kernel_body, int_header,
3433+
int_footer);
3434+
Visitor.VisitRecordFields(KernelObj, kernel_decl, kernel_body, int_header,
3435+
int_footer);
34243436

34253437
if (ParmVarDecl *KernelHandlerArg =
34263438
getSyclKernelHandlerArg(KernelCallerFunc)) {
@@ -4157,7 +4169,7 @@ void SYCLIntegrationHeader::emit(raw_ostream &O) {
41574169
O << "\n";
41584170
}
41594171

4160-
bool SYCLIntegrationHeader::emit(const StringRef &IntHeaderName) {
4172+
bool SYCLIntegrationHeader::emit(StringRef IntHeaderName) {
41614173
if (IntHeaderName.empty())
41624174
return false;
41634175
int IntHeaderFD = 0;
@@ -4229,11 +4241,31 @@ void SYCLIntegrationHeader::setCallsThisGroup(bool B) {
42294241
K->FreeFunctionCalls.CallsThisGroup = B;
42304242
}
42314243

4232-
SYCLIntegrationHeader::SYCLIntegrationHeader(DiagnosticsEngine &_Diag,
4233-
bool _UnnamedLambdaSupport,
4244+
SYCLIntegrationHeader::SYCLIntegrationHeader(bool _UnnamedLambdaSupport,
42344245
Sema &_S)
42354246
: UnnamedLambdaSupport(_UnnamedLambdaSupport), S(_S) {}
42364247

4248+
// Post-compile integration header support.
4249+
bool SYCLIntegrationFooter::emit(StringRef IntHeaderName) {
4250+
if (IntHeaderName.empty())
4251+
return false;
4252+
int IntHeaderFD = 0;
4253+
std::error_code EC =
4254+
llvm::sys::fs::openFileForWrite(IntHeaderName, IntHeaderFD);
4255+
if (EC) {
4256+
llvm::errs() << "Error: " << EC.message() << "\n";
4257+
// compilation will fail on absent include file - don't need to fail here
4258+
return false;
4259+
}
4260+
llvm::raw_fd_ostream Out(IntHeaderFD, true /*close in destructor*/);
4261+
return emit(Out);
4262+
}
4263+
4264+
bool SYCLIntegrationFooter::emit(raw_ostream &O) {
4265+
O << "// Integration Footer contents to go here.\n";
4266+
return true;
4267+
}
4268+
42374269
// -----------------------------------------------------------------------------
42384270
// Utility class methods
42394271
// -----------------------------------------------------------------------------
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// RUN: %clang_cc1 -fsycl-is-device -triple spir64-unknown-unknown-sycldevice -fsycl-int-footer=%t.h %s -emit-llvm -o %t.ll
2+
// RUN: FileCheck -input-file=%t.h %s
3+
4+
// CHECK: // Integration Footer contents to go here.
5+
6+
#include "Inputs/sycl.hpp"
7+
8+
int main() {
9+
cl::sycl::kernel_single_task<class first_kernel>([]() {});
10+
}

0 commit comments

Comments
 (0)