llvmorg-github-actions[bot] wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: Maryam Moghadas (maryammo)

<details>
<summary>Changes</summary>

Add -mcsect[=&lt;qualifier&gt;]/-mno-csect and #pragma csect(code|static, 
"name") for z/OS. Clang emits the CSECT names as 
zos_csect_code/zos_csect_static module flags; backend support will follow in a 
separate patch.

---

Patch is 22.41 KiB, truncated to 20.00 KiB below, full version: 
https://github.com/llvm/llvm-project/pull/234368.diff


18 Files Affected:

- (modified) clang/docs/LanguageExtensions.md (+38) 
- (modified) clang/include/clang/AST/ASTContext.h (+4) 
- (modified) clang/include/clang/Basic/CodeGenOptions.h (+3) 
- (modified) clang/include/clang/Basic/DiagnosticSemaKinds.td (+4) 
- (modified) clang/include/clang/Basic/TokenKinds.def (+3) 
- (modified) clang/include/clang/Options/Options.td (+5) 
- (modified) clang/include/clang/Parse/Parser.h (+5) 
- (modified) clang/include/clang/Sema/Sema.h (+4) 
- (modified) clang/lib/CodeGen/CodeGenModule.cpp (+22) 
- (modified) clang/lib/Driver/ToolChains/Clang.cpp (+25) 
- (modified) clang/lib/Frontend/CompilerInvocation.cpp (+10) 
- (modified) clang/lib/Parse/ParsePragma.cpp (+110) 
- (modified) clang/lib/Parse/Parser.cpp (+3) 
- (modified) clang/lib/Sema/SemaAttr.cpp (+20) 
- (added) clang/test/CodeGen/SystemZ/zos-csect-option-pragma.c (+29) 
- (added) clang/test/CodeGen/SystemZ/zos-csect-option.c (+19) 
- (added) clang/test/CodeGen/SystemZ/zos-csect-pragma-diag.c (+13) 
- (added) clang/test/CodeGen/SystemZ/zos-csect-pragma.c (+11) 


``````````diff
diff --git a/clang/docs/LanguageExtensions.md b/clang/docs/LanguageExtensions.md
index 3db8d083c40756..e9dc6530a61aec 100644
--- a/clang/docs/LanguageExtensions.md
+++ b/clang/docs/LanguageExtensions.md
@@ -5650,6 +5650,44 @@ The builtins return 0 if the values are equal, or 1 if 
they are unequal.
 
   Generates a 16-byte compare-and-swap using the CDSG instruction.
 
+#### z/OS CSECT pragma
+
+Clang supports the `-mcsect`, `-mcsect=<qualifier>`, and `-mno-csect` options,
+and the `#pragma csect` directive, to control CSECT (control section) names in
+the output object module on z/OS.
+
+The CSECT name specified by the option has the following syntax:
+
+`qualifier#basename#suffix`
+
+- `qualifier` is the `<qualifier>` specified by `-mcsect=<qualifier>`.
+- `basename` is the output file name with path information and the right-most
+  extension information removed. If `qualifier` is empty, the syntax becomes
+  just `basename#suffix`.
+- `suffix` is `C` for the code section and `S` for the static section.
+
+Specifying `-mcsect=` is equivalent to specifying `-mcsect`.
+`-mno-csect` is the default.
+
+The `#pragma csect` directive, which must appear at file scope, sets the CSECT
+name for the code or static section:
+
+```c
+#pragma csect(code, "name")
+#pragma csect(static, "name")
+```
+
+There can be at most one `#pragma csect` directive for each section type
+(code or static) per translation unit; duplicates are warned and ignored.
+
+The code and static section names set by `#pragma csect` must be different;
+using the same name for both results in an error.
+
+`#pragma csect(test, "name")` is accepted and ignored.
+
+When both `#pragma csect` and the `-mcsect` option are specified, the
+`#pragma csect` overrides the names generated by the option.
+
 ## Extensions for Static Analysis
 
 Clang supports additional attributes that are useful for documenting program
diff --git a/clang/include/clang/AST/ASTContext.h 
b/clang/include/clang/AST/ASTContext.h
index 1349637273d1e7..e8cf4a0f3f0ea0 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -3978,6 +3978,10 @@ OPT_LIST(V)
 
   llvm::StringMap<SectionInfo> SectionInfos;
 
+  /// Names set by '#pragma csect(code/static, "name")' on z/OS.
+  std::string PragmaCsectStatic;
+  std::string PragmaCsectCode;
+
   /// Return a new OMPTraitInfo object owned by this context.
   OMPTraitInfo &getNewOMPTraitInfo();
 
diff --git a/clang/include/clang/Basic/CodeGenOptions.h 
b/clang/include/clang/Basic/CodeGenOptions.h
index ecd1a63d6de4f3..e77a334445ddb1 100644
--- a/clang/include/clang/Basic/CodeGenOptions.h
+++ b/clang/include/clang/Basic/CodeGenOptions.h
@@ -624,6 +624,9 @@ class CodeGenOptions : public CodeGenOptionsBase {
   /// If threshold option is not specified, it is disabled by default.
   std::optional<uint64_t> DiagnosticsHotnessThreshold = 0;
 
+  /// Specifies the csect name (qualifier & basename) on z/OS.
+  std::optional<std::string> CsectName;
+
   /// The maximum percentage profiling weights can deviate from the expected
   /// values in order to be included in misexpect diagnostics.
   std::optional<uint32_t> DiagnosticsMisExpectTolerance = 0;
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 48b166d2a48a05..090bf2bdc78bb7 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -1296,6 +1296,10 @@ def note_surrounding_namespace_starts_here : Note<
 def warn_failed_to_resolve_pragma : Warning<
   "failed to resolve '#pragma %0' to a declaration">,
   InGroup<IgnoredPragmas>;
+def warn_duplicate_pragma : Warning<"duplicate '#pragma %0' is ignored">,
+  InGroup<IgnoredPragmas>;
+def err_conflicting_pragma : Error<
+  "external name '%0' in pragma %1 conflicts with another csect name">;
 def warn_pragma_not_applied : Warning<
   "#pragma %0 is applicable to symbols with external linkage only; "
   "not applied to %1">,
diff --git a/clang/include/clang/Basic/TokenKinds.def 
b/clang/include/clang/Basic/TokenKinds.def
index 528825ad68b8dc..5608871d4fb260 100644
--- a/clang/include/clang/Basic/TokenKinds.def
+++ b/clang/include/clang/Basic/TokenKinds.def
@@ -902,6 +902,9 @@ PRAGMA_ANNOTATION(pragma_attribute)
 // Annotation for C/C++ #pragma export(ident)
 PRAGMA_ANNOTATION(pragma_export)
 
+// Annotation for #pragma csect(ident, str lit)
+PRAGMA_ANNOTATION(pragma_csect)
+
 // Annotation for the riscv pragma directives - #pragma clang riscv intrinsic 
...
 PRAGMA_ANNOTATION(pragma_riscv)
 
diff --git a/clang/include/clang/Options/Options.td 
b/clang/include/clang/Options/Options.td
index 09f614b1e8b078..d35912bec0a345 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -5629,6 +5629,11 @@ def march_EQ : Joined<["-"], "march=">, Group<m_Group>,
   Flags<[TargetSpecific]>, Visibility<[ClangOption, CLOption, DXCOption, 
FlangOption]>,
   HelpText<"For a list of available architectures for the target use 
'-mcpu=help'">;
 def mzos_target_EQ : Joined<["-"], "mzos-target=">, Group<m_Group>, 
Visibility<[ClangOption, CC1Option]>, HelpText<"Set the z/OS release of the 
runtime environment">;
+def mcsect_EQ : Joined<["-"], "mcsect=">, Group<m_Group>, 
Visibility<[ClangOption, CC1Option]>,
+  HelpText<"Set CSECT names in the output object module">;
+def mcsect : Flag<["-"], "mcsect">, Group<m_Group>, Visibility<[ClangOption, 
CC1Option]>, Alias<mcsect_EQ>;
+def mno_csect : Flag<["-"], "mno-csect">, Group<m_Group>, 
Visibility<[ClangOption, CC1Option]>,
+  HelpText<"Do not set CSECT names in the output object module">;
 def masm_EQ : Joined<["-"], "masm=">, Group<m_Group>, Visibility<[ClangOption, 
FlangOption]>;
 def inline_asm_EQ : Joined<["-"], "inline-asm=">, Group<m_Group>,
   Visibility<[ClangOption, CC1Option]>,
diff --git a/clang/include/clang/Parse/Parser.h 
b/clang/include/clang/Parse/Parser.h
index 9a1abd4f3872de..ae18aea25f978f 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -7188,6 +7188,7 @@ class Parser : public CodeCompletionHandler {
   std::unique_ptr<PragmaHandler> MaxTokensHerePragmaHandler;
   std::unique_ptr<PragmaHandler> MaxTokensTotalPragmaHandler;
   std::unique_ptr<PragmaHandler> ExportHandler;
+  std::unique_ptr<PragmaHandler> CsectHandler;
   std::unique_ptr<PragmaHandler> RISCVPragmaHandler;
 
   /// Initialize all pragma handlers.
@@ -7315,6 +7316,10 @@ class Parser : public CodeCompletionHandler {
   /// #pragma export ...
   void HandlePragmaExport();
 
+  /// Handle the annotation token produced for
+  /// #pragma csect(...)
+  void HandlePragmaCsect();
+
   ///@}
 
   //
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 711e083e4cedd5..ef061647d93f53 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -2391,6 +2391,10 @@ class Sema final : public SemaBase {
   void ActOnPragmaExport(IdentifierInfo *IdentId, SourceLocation ExportNameLoc,
                          Scope *curScope);
 
+  /// ActOnPragmaCsect - called on well-formed '\#pragma csect'
+  void ActOnPragmaCsect(StringRef SectionKind, SourceLocation SectionLoc,
+                        StringRef SectionName);
+
   /// Only called on function definitions; if there is a pragma in scope
   /// with the effect of a range-based optnone, consider marking the function
   /// with attribute optnone.
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp 
b/clang/lib/CodeGen/CodeGenModule.cpp
index bf03e10f9fb422..125a83592d05e8 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -1533,6 +1533,28 @@ void CodeGenModule::Release() {
     // Multiple modes will be supported here.
     getModule().addModuleFlag(llvm::Module::Error, "zos_le_char_mode",
                               llvm::MDString::get(VMContext, "ascii"));
+
+    if (!Context.PragmaCsectCode.empty()) {
+      getModule().addModuleFlag(
+          llvm::Module::Error, "zos_csect_code",
+          llvm::MDString::get(VMContext, Context.PragmaCsectCode));
+    } else if (getCodeGenOpts().CsectName) {
+      getModule().addModuleFlag(
+          llvm::Module::Error, "zos_csect_code",
+          llvm::MDString::get(VMContext,
+                              StringRef(*(getCodeGenOpts().CsectName) + "C")));
+    }
+
+    if (!Context.PragmaCsectStatic.empty()) {
+      getModule().addModuleFlag(
+          llvm::Module::Error, "zos_csect_static",
+          llvm::MDString::get(VMContext, Context.PragmaCsectStatic));
+    } else if (getCodeGenOpts().CsectName) {
+      getModule().addModuleFlag(
+          llvm::Module::Error, "zos_csect_static",
+          llvm::MDString::get(VMContext,
+                              StringRef(*(getCodeGenOpts().CsectName) + "S")));
+    }
   }
 
   llvm::Triple T = Context.getTargetInfo().getTriple();
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp 
b/clang/lib/Driver/ToolChains/Clang.cpp
index eb7bd3ad1ad5e2..163fb27c46fb5e 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -5954,6 +5954,31 @@ void Clang::ConstructJob(Compilation &C, const JobAction 
&JA,
     }
   }
 
+  if (RawTriple.isOSzOS()) {
+    if (Args.hasFlag(options::OPT_mcsect_EQ, options::OPT_mno_csect, false)) {
+      SmallString<256> CsectArg("-mcsect=");
+      StringRef Qualifier;
+      if (const Arg *A = Args.getLastArg(options::OPT_mcsect_EQ))
+        Qualifier = A->getValue();
+      if (!Qualifier.empty()) {
+        CsectArg += Qualifier;
+        CsectArg += "#";
+      }
+
+      SmallString<64> OutputName;
+      if (Arg *OutputOpt = Args.getLastArg(options::OPT_o))
+        OutputName = OutputOpt->getValue();
+      else if (Output.isFilename())
+        OutputName = Output.getFilename();
+
+      CsectArg += llvm::sys::path::stem(OutputName);
+      CsectArg += "#";
+      CmdArgs.push_back(Args.MakeArgString(CsectArg));
+    } else {
+      CmdArgs.push_back("-mno-csect");
+    }
+  }
+
   llvm::Reloc::Model RelocationModel;
   unsigned PICLevel;
   bool IsPIE;
diff --git a/clang/lib/Frontend/CompilerInvocation.cpp 
b/clang/lib/Frontend/CompilerInvocation.cpp
index c9281c2a6d6b41..34a73f07eaf352 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -1828,6 +1828,11 @@ void CompilerInvocationBase::GenerateCodeGenArgs(const 
CodeGenOptions &Opts,
     break;
   }
 
+  if (Opts.CsectName)
+    GenerateArg(Consumer, OPT_mcsect_EQ, Twine(*Opts.CsectName));
+  else
+    GenerateArg(Consumer, OPT_mno_csect);
+
   if (Opts.StaticClosure)
     GenerateArg(Consumer, OPT_static_libclosure);
 }
@@ -2331,6 +2336,11 @@ bool CompilerInvocation::ParseCodeGenArgs(CodeGenOptions 
&Opts, ArgList &Args,
   if (!Opts.EmitIEEENaNCompliantInsts && !LangOptsRef.NoHonorNaNs)
     Diags.Report(diag::err_drv_amdgpu_ieee_without_no_honor_nans);
 
+  if (Args.hasFlag(OPT_mcsect_EQ, OPT_mno_csect, false)) {
+    const Arg *A = Args.getLastArg(OPT_mcsect_EQ);
+    Opts.CsectName = A->getValue();
+  }
+
   Opts.StaticClosure = Args.hasArg(options::OPT_static_libclosure);
 
   if (!Opts.HLSLRecordCommandLine.empty()) {
diff --git a/clang/lib/Parse/ParsePragma.cpp b/clang/lib/Parse/ParsePragma.cpp
index 04e7bb5a9b7dd9..3c6ecbef98cbd0 100644
--- a/clang/lib/Parse/ParsePragma.cpp
+++ b/clang/lib/Parse/ParsePragma.cpp
@@ -395,6 +395,12 @@ struct PragmaExportHandler : public PragmaHandler {
                     Token &FirstToken) override;
 };
 
+struct PragmaCsectHandler : public PragmaHandler {
+  PragmaCsectHandler() : PragmaHandler("csect") {}
+  void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
+                    Token &Tok) override;
+};
+
 struct PragmaRISCVHandler : public PragmaHandler {
   PragmaRISCVHandler(Sema &Actions)
       : PragmaHandler("riscv"), Actions(Actions) {}
@@ -562,6 +568,8 @@ void Parser::initializePragmaHandlers() {
   if (getLangOpts().ZOSExt) {
     ExportHandler = std::make_unique<PragmaExportHandler>();
     PP.AddPragmaHandler(ExportHandler.get());
+    CsectHandler = std::make_unique<PragmaCsectHandler>();
+    PP.AddPragmaHandler(CsectHandler.get());
   }
 
   if (getTargetInfo().getTriple().isRISCV()) {
@@ -702,6 +710,8 @@ void Parser::resetPragmaHandlers() {
   if (getLangOpts().ZOSExt) {
     PP.RemovePragmaHandler(ExportHandler.get());
     ExportHandler.reset();
+    PP.RemovePragmaHandler(CsectHandler.get());
+    CsectHandler.reset();
   }
 
   if (getTargetInfo().getTriple().isRISCV()) {
@@ -1464,6 +1474,19 @@ void Parser::HandlePragmaExport() {
   zOSHandlePragmaHelper(tok::annot_pragma_export);
 }
 
+void Parser::HandlePragmaCsect() {
+  assert(Tok.is(tok::annot_pragma_csect));
+  StringRef *SectionName = static_cast<StringRef *>(Tok.getAnnotationValue());
+  assert(SectionName);
+  SourceLocation PragmaLoc = Tok.getLocation();
+
+  ConsumeAnnotationToken();
+
+  llvm::StringRef SectionKind = Tok.getIdentifierInfo()->getName();
+  ConsumeToken();
+  Actions.ActOnPragmaCsect(SectionKind, PragmaLoc, *SectionName);
+}
+
 static std::string PragmaLoopHintString(Token PragmaName, Token Option) {
   StringRef Str = PragmaName.getIdentifierInfo()->getName();
   std::string ClangLoopStr("clang loop ");
@@ -4259,3 +4282,90 @@ void PragmaRISCVHandler::HandlePragma(Preprocessor &PP,
   else if (II->isStr("andes_vector"))
     Actions.RISCV().DeclareAndesVectorBuiltins = true;
 }
+
+/// Handle #pragma csect.
+void PragmaCsectHandler::HandlePragma(Preprocessor &PP,
+                                      PragmaIntroducer Introducer, Token &Tok) 
{
+  SourceLocation CSectLoc = Tok.getLocation();
+
+  PP.Lex(Tok);
+  if (Tok.isNot(tok::l_paren)) {
+    PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "csect";
+    return;
+  }
+
+  PP.LexUnexpandedToken(Tok);
+  bool ValidPragma = false;
+  bool AcceptAndIgnore = false;
+  switch (Tok.getKind()) {
+  case tok::kw_static:
+    ValidPragma = true;
+    break;
+  case tok::identifier: {
+    assert(Tok.getIdentifierInfo());
+    StringRef Section = Tok.getIdentifierInfo()->getName();
+    AcceptAndIgnore = Section.equals_insensitive("test");
+    if (AcceptAndIgnore || Section.equals_insensitive("code") ||
+        Section.equals_insensitive("static"))
+      ValidPragma = true;
+    break;
+  }
+  default:
+    break;
+  }
+  if (!ValidPragma) {
+    PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
+        << "csect";
+    return;
+  }
+  Token SectionKind = Tok;
+
+  PP.Lex(Tok);
+  if (Tok.isNot(tok::comma)) {
+    PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_comma) << "csect";
+    return;
+  }
+
+  PP.Lex(Tok);
+  if (Tok.isNot(tok::string_literal)) {
+    PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_string) << "csect";
+    return;
+  }
+
+  std::string SectionName;
+  if (!PP.FinishLexStringLiteral(Tok, SectionName, "pragma csect",
+                                 /*AllowMacroExpansion*/ false)) {
+    return;
+  }
+
+  if (Tok.isNot(tok::r_paren)) {
+    PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) << "csect";
+    return;
+  }
+
+  PP.Lex(Tok);
+  if (Tok.isNot(tok::eod)) {
+    PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
+        << "csect";
+    return;
+  }
+
+  if (AcceptAndIgnore) {
+    // accept and ignore #pragma csect(test, "STRING LITERAL");
+    return;
+  }
+
+  auto *SectionNameRef = new (PP.getPreprocessorAllocator())
+      StringRef(StringRef(SectionName).copy(PP.getPreprocessorAllocator()));
+
+  MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(2),
+                              2);
+  Toks[0].startToken();
+  Toks[0].setKind(tok::annot_pragma_csect);
+  Toks[0].setLocation(CSectLoc);
+  Toks[0].setAnnotationValue(static_cast<void *>(SectionNameRef));
+  Toks[1] = SectionKind;
+
+  PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
+                      /*IsReinject=*/false);
+}
diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp
index c5d6a17fbfcd34..d5e5a982f24302 100644
--- a/clang/lib/Parse/Parser.cpp
+++ b/clang/lib/Parse/Parser.cpp
@@ -823,6 +823,9 @@ Parser::ParseExternalDeclaration(ParsedAttributes &Attrs,
   case tok::annot_pragma_export:
     HandlePragmaExport();
     return nullptr;
+  case tok::annot_pragma_csect:
+    HandlePragmaCsect();
+    return nullptr;
   case tok::semi:
     // Either a C++11 empty-declaration or attribute-declaration.
     SingleDecl =
diff --git a/clang/lib/Sema/SemaAttr.cpp b/clang/lib/Sema/SemaAttr.cpp
index 35d14a4444595a..6aa71f331d1fdb 100644
--- a/clang/lib/Sema/SemaAttr.cpp
+++ b/clang/lib/Sema/SemaAttr.cpp
@@ -1676,3 +1676,23 @@ bool Sema::checkCommonAttributeFeatures(const Stmt *S, 
const ParsedAttr &A,
                                         bool SkipArgCountCheck) {
   return ::checkCommonAttributeFeatures(*this, S, A, SkipArgCountCheck);
 }
+
+void Sema::ActOnPragmaCsect(StringRef SectionKind, SourceLocation SectionLoc,
+                            StringRef SectionName) {
+  if (SectionKind.equals_insensitive("static")) {
+    if (!Context.PragmaCsectStatic.empty())
+      Diag(SectionLoc, diag::warn_duplicate_pragma) << "csect";
+    else if (Context.PragmaCsectCode == SectionName)
+      Diag(SectionLoc, diag::err_conflicting_pragma) << SectionName << "csect";
+    else
+      Context.PragmaCsectStatic = SectionName.str();
+  } else if (SectionKind.equals_insensitive("code")) {
+    if (!Context.PragmaCsectCode.empty())
+      Diag(SectionLoc, diag::warn_duplicate_pragma) << "csect";
+    else if (Context.PragmaCsectStatic == SectionName)
+      Diag(SectionLoc, diag::err_conflicting_pragma) << SectionName << "csect";
+    else
+      Context.PragmaCsectCode = SectionName.str();
+  } else
+    llvm_unreachable("invalid Csect kind");
+}
diff --git a/clang/test/CodeGen/SystemZ/zos-csect-option-pragma.c 
b/clang/test/CodeGen/SystemZ/zos-csect-option-pragma.c
new file mode 100644
index 00000000000000..76d1c78902f19b
--- /dev/null
+++ b/clang/test/CodeGen/SystemZ/zos-csect-option-pragma.c
@@ -0,0 +1,29 @@
+// REQUIRES: systemz-registered-target
+
+// RUN: %clang -S -emit-llvm --target=s390x-none-zos %s -o outputfile2.ll && 
cat outputfile2.ll | FileCheck %s --check-prefix=CHECK-NOCSECT
+// RUN: %clang -S -emit-llvm --target=s390x-none-zos -mcsect %s -o 
outputfile2.ll && cat outputfile2.ll | FileCheck %s
+// RUN: %clang -S -emit-llvm --target=s390x-none-zos -mcsect= %s -o 
outputfile2.ll && cat outputfile2.ll | FileCheck %s
+// RUN: %clang -S -emit-llvm --target=s390x-none-zos -mcsect=abc %s -o 
outputfile2.ll && cat outputfile2.ll | FileCheck %s 
--check-prefix=CHECK-QUALIFIER
+// RUN: %clang -S -emit-llvm --target=s390x-none-zos -mno-csect %s -o 
outputfile2.ll && cat outputfile2.ll | FileCheck %s --check-prefix=CHECK-NOCSECT
+// RUN: %clang -S -emit-llvm --target=s390x-none-zos -mcsect %s && cat 
zos-csect-option-pragma.ll | FileCheck %s --check-prefix=CHECK-NOOUTFILE
+// RUN: %clang -S -emit-llvm --target=s390x-none-zos -mcsect= %s && cat 
zos-csect-option-pragma.ll | FileCheck %s --check-prefix=CHECK-NOOUTFILE
+// RUN: %clang -S -emit-llvm --target=s390x-none-zos -mcsect=cde %s && cat 
zos-csect-option-pragma.ll | FileCheck %s 
--check-prefix=CHECK-NOOUTFILE-QUALIFIER
+
+#pragma csect(code, "csectcode")
+
+int main() { return 0; }
+
+// CHECK: !{i32 1, !"zos_csect_code", !"csectcode"}
+// CHECK: !{i32 1, !"zos_csect_static", !"outputfile2#S"}
+
+// CHECK-QUALIFIER: !{i32 1, !"zos_csect_code", !"csectcode"}
+// CHECK-QUALIFIER: !{i32 1, !"zos_csect_static", !"abc#outputfile2#S"}
+
+// CHECK-NOCSECT: !{i32 1, !"zos_csect_code", !"csectcode"}
+// CHECK-NOCSECT-NOT: zos_csect_static
+
+// CHECK-NOOUTFILE: !{i32 1, !"zos_csect_code", !"csectcode"}
+// CHECK-NOOUTFILE: !{i32 1, !"zos_csect_static", !"zos-csect-option-pragma#S"}
+
+// CHECK-NOOUTFILE-QUALIFIER: !{i32 1, !"zos_csect_code", !"csectcode"}
+// CHECK-NOOUTFILE-QUALIFIER: !{i32 1, !"zos_csect_static", 
!"cde#zos-csect-option-pragma#S"}
diff --git a/clang/test/CodeGen/SystemZ/zos-csect-option.c 
b/clang/test/CodeGen/SystemZ/zos-csect-option.c
new file mode 100644
index 00000000000000..a515099949a53a
--- /dev/null
+++ b/clang/test/CodeGen/SystemZ/zos-csect-option.c
@@ -0,0 +1,19 @@
+// REQUIRES: systemz-registered-target
+
+// RUN: %clang -S -emit-llvm --target=s390x-none-zos %s -o outputfile.ll && 
cat outputfile.ll | FileCheck...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/234368
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to