edward-jones updated this revision to Diff 389520.

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D109372/new/

https://reviews.llvm.org/D109372

Files:
  clang/include/clang/Basic/Attr.td
  clang/include/clang/Basic/AttrDocs.td
  clang/include/clang/Basic/DiagnosticDriverKinds.td
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/include/clang/Basic/LangOptions.def
  clang/include/clang/Driver/Options.td
  clang/lib/CodeGen/CGCall.cpp
  clang/lib/CodeGen/CodeGenModule.cpp
  clang/lib/Driver/ToolChains/Arch/RISCV.cpp
  clang/lib/Driver/ToolChains/Clang.cpp
  clang/lib/Sema/SemaDecl.cpp
  clang/lib/Sema/SemaDeclAttr.cpp
  clang/test/CodeGen/riscv-overlay.c
  clang/test/Driver/riscv-overlay.c
  clang/test/Misc/pragma-attribute-supported-attributes-list.test
  clang/test/Sema/riscv-overlay-attr.c
  clang/test/Sema/riscv-overlay-namespace.cpp

Index: clang/test/Sema/riscv-overlay-namespace.cpp
===================================================================
--- /dev/null
+++ clang/test/Sema/riscv-overlay-namespace.cpp
@@ -0,0 +1,20 @@
+// RUN: %clang_cc1 %s -triple riscv32-unknown-elf -verify -fsyntax-only -moverlay
+// RUN: %clang_cc1 %s -triple riscv64-unknown-elf -verify -fsyntax-only -moverlay
+
+namespace {
+class foo {
+public:
+  static int X() __attribute__((overlay_call)) { return 0; } // expected-error {{functions marked with 'overlay_call' attribute must have external linkage}}
+};
+} // end of anonymous namespace
+
+namespace X {
+class bar {
+public:
+  static int X() __attribute__((overlay_call)) { return 1; }
+};
+} // end of namespace X
+
+extern "C" {
+int main(void) { return foo::X() + X::bar::X(); }
+}
Index: clang/test/Sema/riscv-overlay-attr.c
===================================================================
--- /dev/null
+++ clang/test/Sema/riscv-overlay-attr.c
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 -triple riscv32 -moverlay -fsyntax-only -verify %s
+// RUN: %clang_cc1 -triple riscv64 -moverlay -fsyntax-only -verify %s
+
+int notAFunction __attribute__((overlay_call));
+// expected-warning@-1 {{'overlay_call' attribute only applies to functions}}
+
+void incompatForwardDecl(int x);
+void __attribute__((overlay_call)) incompatForwardDecl(int x) {}
+// expected-error@-1 {{redeclaration of 'incompatForwardDecl' must not have the 'overlay_call' attribute}}
+// expected-note@-3 {{previous definition is here}}
+
+static void staticcall() __attribute__((overlay_call)) {}
+// expected-error@-1 {{functions marked with 'overlay_call' attribute must have external linkage}}
+
+static void __attribute__((overlay_call)) staticcall2() {}
+// expected-error@-1 {{functions marked with 'overlay_call' attribute must have external linkage}}
Index: clang/test/Misc/pragma-attribute-supported-attributes-list.test
===================================================================
--- clang/test/Misc/pragma-attribute-supported-attributes-list.test
+++ clang/test/Misc/pragma-attribute-supported-attributes-list.test
@@ -147,6 +147,7 @@
 // CHECK-NEXT: PassObjectSize (SubjectMatchRule_variable_is_parameter)
 // CHECK-NEXT: PatchableFunctionEntry (SubjectMatchRule_function, SubjectMatchRule_objc_method)
 // CHECK-NEXT: Pointer (SubjectMatchRule_record_not_is_union)
+// CHECK-NEXT: RISCVOverlayCall (SubjectMatchRule_function)
 // CHECK-NEXT: ReleaseHandle (SubjectMatchRule_variable_is_parameter)
 // CHECK-NEXT: RenderScriptKernel (SubjectMatchRule_function)
 // CHECK-NEXT: ReqdWorkGroupSize (SubjectMatchRule_function)
Index: clang/test/Driver/riscv-overlay.c
===================================================================
--- /dev/null
+++ clang/test/Driver/riscv-overlay.c
@@ -0,0 +1,5 @@
+// Check that ComRV Driver Arguments
+
+// RUN: not %clang -target riscv32 -moverlay %s -o %t.o -mabi=ilp32f 2>&1 \
+// RUN:   | FileCheck -check-prefix=INVALID-ABI %s
+// INVALID-ABI: invalid ABI 'ilp32f' when using '-moverlay'
Index: clang/test/CodeGen/riscv-overlay.c
===================================================================
--- /dev/null
+++ clang/test/CodeGen/riscv-overlay.c
@@ -0,0 +1,11 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --check-attributes
+// RUN: %clang_cc1 -triple riscv32 -moverlay -emit-llvm %s -o - \
+// RUN:    | FileCheck %s
+
+// CHECK-LABEL: @test_overlay_func(
+// CHECK-SAME: #0
+// CHECK: attributes #0 = {
+// CHECK-SAME: "overlay"
+int __attribute__((overlay_call)) test_overlay_func(void) {
+  return 5;
+}
Index: clang/lib/Sema/SemaDeclAttr.cpp
===================================================================
--- clang/lib/Sema/SemaDeclAttr.cpp
+++ clang/lib/Sema/SemaDeclAttr.cpp
@@ -2039,6 +2039,33 @@
   D->addAttr(::new (S.Context) CmseNSEntryAttr(S.Context, AL));
 }
 
+static void handleRISCVOverlayAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+  if (!S.getLangOpts().Overlay) {
+    S.Diag(AL.getRange().getBegin(), diag::warn_attribute_ignored_overlay)
+        << AL;
+    return;
+  }
+
+  if (isFunctionOrMethod(D)) {
+    const auto *ND = cast<NamedDecl>(D);
+    if (!ND->isExternallyVisible()) {
+      S.Diag(AL.getLoc(), diag::err_overlay_func_external_linkage);
+      AL.setInvalid();
+      return;
+    }
+
+    // 'overlay' on a function implies 'noinline'
+    Attr *A = ::new (S.Context) NoInlineAttr(S.Context, AL);
+    A->setImplicit(true);
+    D->addAttr(A);
+  }
+
+  if (AL.getKind() == ParsedAttr::AT_RISCVOverlayCall)
+    handleSimpleAttribute<RISCVOverlayCallAttr>(S, D, AL);
+  else
+    handleSimpleAttribute<RISCVOverlayDataAttr>(S, D, AL);
+}
+
 static void handleNakedAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
   if (AL.isDeclspecAttribute()) {
     const auto &Triple = S.getASTContext().getTargetInfo().getTriple();
@@ -8264,6 +8291,10 @@
   case ParsedAttr::AT_CmseNSEntry:
     handleCmseNSEntryAttr(S, D, AL);
     break;
+  case ParsedAttr::AT_RISCVOverlayCall:
+  case ParsedAttr::AT_RISCVOverlayData:
+    handleRISCVOverlayAttr(S, D, AL);
+    break;
   case ParsedAttr::AT_StdCall:
   case ParsedAttr::AT_CDecl:
   case ParsedAttr::AT_FastCall:
Index: clang/lib/Sema/SemaDecl.cpp
===================================================================
--- clang/lib/Sema/SemaDecl.cpp
+++ clang/lib/Sema/SemaDecl.cpp
@@ -3358,6 +3358,15 @@
     }
   }
 
+  bool NewIsOverlayCall = New->hasAttr<RISCVOverlayCallAttr>();
+  bool OldIsOverlayCall = Old->hasAttr<RISCVOverlayCallAttr>();
+  if (NewIsOverlayCall != OldIsOverlayCall) {
+    Diag(New->getLocation(), diag::err_overlay_mismatch)
+        << New << OldIsOverlayCall;
+    notePreviousDefinition(Old, New->getLocation());
+    return true;
+  }
+
   if (const auto *ILA = New->getAttr<InternalLinkageAttr>())
     if (!Old->hasAttr<InternalLinkageAttr>()) {
       Diag(New->getLocation(), diag::err_attribute_missing_on_first_decl)
Index: clang/lib/Driver/ToolChains/Clang.cpp
===================================================================
--- clang/lib/Driver/ToolChains/Clang.cpp
+++ clang/lib/Driver/ToolChains/Clang.cpp
@@ -2095,6 +2095,15 @@
     CmdArgs.push_back("-tune-cpu");
     CmdArgs.push_back(Args.MakeArgString(TuneCPU));
   }
+
+  // If comrv mode is requested, pass on this flag, and produce an error if an
+  // invalid ABI has been requested
+  if (Args.getLastArg(options::OPT_moverlay)) {
+    CmdArgs.push_back("-moverlay");
+    if (ABIName != "ilp32")
+      getToolChain().getDriver().Diag(diag::err_drv_invalid_riscv_abi_moverlay)
+          << ABIName;
+  }
 }
 
 void Clang::AddSparcTargetArgs(const ArgList &Args,
Index: clang/lib/Driver/ToolChains/Arch/RISCV.cpp
===================================================================
--- clang/lib/Driver/ToolChains/Arch/RISCV.cpp
+++ clang/lib/Driver/ToolChains/Arch/RISCV.cpp
@@ -492,6 +492,14 @@
   if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ))
     getRISCFeaturesFromMcpu(D, Triple, Args, A, A->getValue(), Features);
 
+  // Extra register reservations required to handle -moverlay
+  if (Args.hasArg(options::OPT_moverlay)) {
+    Features.push_back("+reserve-x28"); // Overlay Stack Register
+    Features.push_back("+reserve-x29"); // Overlay Stack Frames Pool Register
+    Features.push_back("+reserve-x30"); // Overlay Address Token Reg
+    Features.push_back("+reserve-x31"); // Overlay Entry Point Address Register
+  }
+
   // Handle features corresponding to "-ffixed-X" options
   if (Args.hasArg(options::OPT_ffixed_x1))
     Features.push_back("+reserve-x1");
Index: clang/lib/CodeGen/CodeGenModule.cpp
===================================================================
--- clang/lib/CodeGen/CodeGenModule.cpp
+++ clang/lib/CodeGen/CodeGenModule.cpp
@@ -1880,6 +1880,10 @@
     if (LangOpts.FunctionAlignment)
       F->setAlignment(llvm::Align(1ull << LangOpts.FunctionAlignment));
 
+  // Overlay functions must have a minimum 4-byte alignment.
+  if (F->getAlignment() < 4 && D->hasAttr<RISCVOverlayCallAttr>())
+    F->setAlignment(llvm::Align(4));
+
   // Some C++ ABIs require 2-byte alignment for member functions, in order to
   // reserve a bit for differentiating between virtual and non-virtual member
   // functions. If the current target's C++ ABI requires this and this is a
@@ -4525,6 +4529,9 @@
   if (CGDebugInfo *DI = getModuleDebugInfo())
     if (getCodeGenOpts().hasReducedDebugInfo())
       DI->EmitGlobalVariable(GV, D);
+
+  if (D->hasAttr<RISCVOverlayDataAttr>())
+    GV->addAttribute("overlay");
 }
 
 void CodeGenModule::EmitExternalVarDeclaration(const VarDecl *D) {
Index: clang/lib/CodeGen/CGCall.cpp
===================================================================
--- clang/lib/CodeGen/CGCall.cpp
+++ clang/lib/CodeGen/CGCall.cpp
@@ -2199,8 +2199,12 @@
   // Collect non-call-site function IR attributes from declaration-specific
   // information.
   if (!AttrOnCallSite) {
-    if (TargetDecl && TargetDecl->hasAttr<CmseNSEntryAttr>())
-      FuncAttrs.addAttribute("cmse_nonsecure_entry");
+    if (TargetDecl) {
+      if (TargetDecl->hasAttr<RISCVOverlayCallAttr>())
+        FuncAttrs.addAttribute("overlay");
+      if (TargetDecl->hasAttr<CmseNSEntryAttr>())
+        FuncAttrs.addAttribute("cmse_nonsecure_entry");
+    }
 
     // Whether tail calls are enabled.
     auto shouldDisableTailCalls = [&] {
Index: clang/include/clang/Driver/Options.td
===================================================================
--- clang/include/clang/Driver/Options.td
+++ clang/include/clang/Driver/Options.td
@@ -3229,6 +3229,10 @@
   HelpText<"Equivalent to -mcmodel=medium, compatible with RISC-V gcc.">;
 def menable_experimental_extensions : Flag<["-"], "menable-experimental-extensions">, Group<m_Group>,
   HelpText<"Enable use of experimental RISC-V extensions.">;
+def moverlay : Flag<["-"], "moverlay">,
+  Group<m_Group>, Flags<[CC1Option]>,
+  HelpText<"Enable RISC-V overlay manager support">,
+  MarshallingInfoFlag<LangOpts<"Overlay">>;
 
 def munaligned_access : Flag<["-"], "munaligned-access">, Group<m_arm_Features_Group>,
   HelpText<"Allow memory accesses to be unaligned (AArch32/AArch64 only)">;
Index: clang/include/clang/Basic/LangOptions.def
===================================================================
--- clang/include/clang/Basic/LangOptions.def
+++ clang/include/clang/Basic/LangOptions.def
@@ -428,6 +428,10 @@
              "Controls how scalar integer arguments are extended in calls "
              "to unprototyped and varargs functions")
 
+LANGOPT(Overlay, 1, 0,
+        "Enable support for use of an overlay system for calls and data "
+        "accesses")
+
 #undef LANGOPT
 #undef COMPATIBLE_LANGOPT
 #undef BENIGN_LANGOPT
Index: clang/include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -309,6 +309,13 @@
   "repeated RISC-V 'interrupt' attribute">, InGroup<IgnoredAttributes>;
 def note_riscv_repeated_interrupt_attribute : Note<
   "repeated RISC-V 'interrupt' attribute is here">;
+def err_overlay_func_external_linkage : Error<
+  "functions marked with 'overlay_call' attribute must have external linkage">;
+def err_overlay_mismatch : Error<
+  "redeclaration of %0 must %select{not |}1have the 'overlay_call' attribute">;
+def warn_attribute_ignored_overlay : Warning<
+  "%0 attribute ignored, use '-moverlay' to enable support">,
+  InGroup<IgnoredAttributes>;
 def warn_unused_parameter : Warning<"unused parameter %0">,
   InGroup<UnusedParameter>, DefaultIgnore;
 def warn_unused_but_set_parameter : Warning<"parameter %0 set but not used">,
Index: clang/include/clang/Basic/DiagnosticDriverKinds.td
===================================================================
--- clang/include/clang/Basic/DiagnosticDriverKinds.td
+++ clang/include/clang/Basic/DiagnosticDriverKinds.td
@@ -32,6 +32,8 @@
 def warn_drv_invalid_arch_name_with_suggestion : Warning<
   "ignoring invalid /arch: argument '%0'; for %select{64|32}1-bit expected one of %2">,
   InGroup<UnusedCommandLineArgument>;
+def err_drv_invalid_riscv_abi_moverlay : Error<
+  "invalid ABI '%0' when using '-moverlay'">;
 def warn_drv_avr_mcu_not_specified : Warning<
   "no target microcontroller specified on command line, cannot "
   "link standard libraries, please pass -mmcu=<mcu name>">,
Index: clang/include/clang/Basic/AttrDocs.td
===================================================================
--- clang/include/clang/Basic/AttrDocs.td
+++ clang/include/clang/Basic/AttrDocs.td
@@ -2142,6 +2142,52 @@
   }];
 }
 
+def RISCVOverlayCallDocs : Documentation {
+  let Category = DocCatFunction;
+  let Heading = "overlay_call (RISCV)";
+  let Content = [{
+Clang supports the ``__attribute__((overlay_call))`` attribute on RISC-V
+targets. This attribute may be attached to a function definition and signifies
+that the function is placed in a software overlay. In order to use this
+attribute the ``-moverlay`` flag must also be specified during compilation.
+
+A function cannot be marked as ``overlay_call`` if it does not have external
+linkage. This includes functions marked ``static`` or defined in an
+anonymous namespace.
+
+When a function is marked with this attribute it is forced to have an
+alignment of at least 4 bytes.
+
+When a function exists in an overlay it can only be called indirectly
+through the RISC-V Overlay Runtime engine. The runtime engine is responsible
+for shuffling overlay functions into resident memory as required. The
+attribute facilities this as follows:
+
+* When referencing functions marked as ``overlay_call`` a 'token' is used
+  instead of an address. This 'token' encodes information for use by the
+  runtime engine.
+* When calling to/from an overlay function the call target (either a
+  token or the address of a resident function) is first stored to an argument
+  register, then a call is performed into the runtime engine.
+* When the address of a ``overlay_call`` function is taken the address
+  of a 'thunk' corresponding to that function is used instead. The
+  'thunk' is a stub in resident memory which can be used in a normal
+  indirect call, but redirects the call through the runtime engine.
+  }];
+}
+
+def RISCVOverlayDataDocs : Documentation {
+  let Category = DocCatVariable;
+  let Heading = "overlay_data (RISCV)";
+  let Content = [{
+Clang supports the ``__attribute__((overlay_data))`` attribute on RISC-V
+targets. This attribute may be attached to a global constant declaration
+and signifies that the value is placed in a software overlay. In order to
+use this attribute the ``-moverlay`` flag must also be specified during
+compilation.
+  }];
+}
+
 def AVRInterruptDocs : Documentation {
   let Category = DocCatFunction;
   let Heading = "interrupt (AVR)";
Index: clang/include/clang/Basic/Attr.td
===================================================================
--- clang/include/clang/Basic/Attr.td
+++ clang/include/clang/Basic/Attr.td
@@ -118,6 +118,11 @@
 def GlobalVar : SubsetSubject<Var,
                              [{S->hasGlobalStorage()}], "global variables">;
 
+def GlobalConst : SubsetSubject<Var,
+                               [{S->hasGlobalStorage() &&
+                                 S->getType().isConstQualified()}],
+                               "global constants">;
+
 def InlineFunction : SubsetSubject<Function,
                              [{S->isInlineSpecified()}], "inline functions">;
 
@@ -1782,6 +1787,18 @@
   let Documentation = [RISCVInterruptDocs];
 }
 
+def RISCVOverlayCall : InheritableAttr, TargetSpecificAttr<TargetRISCV> {
+  let Spellings = [Clang<"overlay_call">];
+  let Subjects = SubjectList<[Function]>;
+  let Documentation = [RISCVOverlayCallDocs];
+}
+
+def RISCVOverlayData : InheritableAttr, TargetSpecificAttr<TargetRISCV> {
+  let Spellings = [Clang<"overlay_data">];
+  let Subjects = SubjectList<[GlobalConst]>;
+  let Documentation = [RISCVOverlayDataDocs];
+}
+
 // This is not a TargetSpecificAttr so that is silently accepted and
 // ignored on other targets as encouraged by the OpenCL spec.
 //
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to