Author: Min-Yih Hsu
Date: 2021-03-08T12:30:57-08:00
New Revision: 5eb7a5814a5c629378ba2a4a45fc65cd7f183c9c

URL: 
https://github.com/llvm/llvm-project/commit/5eb7a5814a5c629378ba2a4a45fc65cd7f183c9c
DIFF: 
https://github.com/llvm/llvm-project/commit/5eb7a5814a5c629378ba2a4a45fc65cd7f183c9c.diff

LOG: [cfe][M68k](7/8) Clang basic support

This is the first patch supporting M68k in Clang
 - Register M68k as a target
 - Target specific CodeGen support
 - Target specific attribute support

Authors: myhsu, m4yers, glaubitz

Differential Revision: https://reviews.llvm.org/D88393

Added: 
    clang/lib/Basic/Targets/M68k.cpp
    clang/lib/Basic/Targets/M68k.h

Modified: 
    clang/include/clang/Basic/Attr.td
    clang/lib/Basic/CMakeLists.txt
    clang/lib/Basic/Targets.cpp
    clang/lib/CodeGen/TargetInfo.cpp
    clang/lib/Sema/SemaDeclAttr.cpp

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/Basic/Attr.td 
b/clang/include/clang/Basic/Attr.td
index 8afa676c133f..9625e7f8f322 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -368,6 +368,7 @@ def TargetBPF : TargetArch<["bpfel", "bpfeb"]>;
 def TargetMips32 : TargetArch<["mips", "mipsel"]>;
 def TargetAnyMips : TargetArch<["mips", "mipsel", "mips64", "mips64el"]>;
 def TargetMSP430 : TargetArch<["msp430"]>;
+def TargetM68k : TargetArch<["m68k"]>;
 def TargetRISCV : TargetArch<["riscv32", "riscv64"]>;
 def TargetX86 : TargetArch<["x86"]>;
 def TargetAnyX86 : TargetArch<["x86", "x86_64"]>;
@@ -772,8 +773,9 @@ def Annotate : InheritableParamAttr {
 }
 
 def ARMInterrupt : InheritableAttr, TargetSpecificAttr<TargetARM> {
-  // NOTE: If you add any additional spellings, MSP430Interrupt's,
-  // MipsInterrupt's and AnyX86Interrupt's spellings must match.
+  // NOTE: If you add any additional spellings, M68kInterrupt's,
+  // MSP430Interrupt's, MipsInterrupt's and AnyX86Interrupt's spellings
+  // must match.
   let Spellings = [GCC<"interrupt">];
   let Args = [EnumArgument<"Interrupt", "InterruptType",
                            ["IRQ", "FIQ", "SWI", "ABORT", "UNDEF", ""],
@@ -1524,8 +1526,8 @@ def MSABI : DeclOrTypeAttr {
 }
 
 def MSP430Interrupt : InheritableAttr, TargetSpecificAttr<TargetMSP430> {
-  // NOTE: If you add any additional spellings, ARMInterrupt's, MipsInterrupt's
-  // and AnyX86Interrupt's spellings must match.
+  // NOTE: If you add any additional spellings, ARMInterrupt's, 
M68kInterrupt's,
+  // MipsInterrupt's and AnyX86Interrupt's spellings must match.
   let Spellings = [GCC<"interrupt">];
   let Args = [UnsignedArgument<"Number">];
   let ParseKind = "Interrupt";
@@ -1541,7 +1543,8 @@ def Mips16 : InheritableAttr, 
TargetSpecificAttr<TargetMips32> {
 
 def MipsInterrupt : InheritableAttr, TargetSpecificAttr<TargetMips32> {
   // NOTE: If you add any additional spellings, ARMInterrupt's,
-  // MSP430Interrupt's and AnyX86Interrupt's spellings must match.
+  // M68kInterrupt's, MSP430Interrupt's and AnyX86Interrupt's spellings
+  // must match.
   let Spellings = [GCC<"interrupt">];
   let Subjects = SubjectList<[Function]>;
   let Args = [EnumArgument<"Interrupt", "InterruptType",
@@ -1573,6 +1576,16 @@ def MipsShortCall : InheritableAttr, 
TargetSpecificAttr<TargetAnyMips> {
   let Documentation = [MipsShortCallStyleDocs];
 }
 
+def M68kInterrupt : InheritableAttr, TargetSpecificAttr<TargetM68k> {
+  // NOTE: If you add any additional spellings, ARMInterrupt's, MipsInterrupt's
+  // MSP430Interrupt's and AnyX86Interrupt's spellings must match.
+  let Spellings = [GNU<"interrupt">];
+  let Args = [UnsignedArgument<"Number">];
+  let ParseKind = "Interrupt";
+  let HasCustomParsing = 1;
+  let Documentation = [Undocumented];
+}
+
 def Mode : Attr {
   let Spellings = [GCC<"mode">];
   let Subjects = SubjectList<[Var, Enum, TypedefName, Field], ErrorDiag>;
@@ -2777,7 +2790,7 @@ def LTOVisibilityPublic : InheritableAttr {
 
 def AnyX86Interrupt : InheritableAttr, TargetSpecificAttr<TargetAnyX86> {
   // NOTE: If you add any additional spellings, ARMInterrupt's,
-  // MSP430Interrupt's and MipsInterrupt's spellings must match.
+  // M68kInterrupt's, MSP430Interrupt's and MipsInterrupt's spellings must 
match.
   let Spellings = [GCC<"interrupt">];
   let Subjects = SubjectList<[HasFunctionProto]>;
   let ParseKind = "Interrupt";

diff  --git a/clang/lib/Basic/CMakeLists.txt b/clang/lib/Basic/CMakeLists.txt
index 709505d502ed..a3a8f8d68962 100644
--- a/clang/lib/Basic/CMakeLists.txt
+++ b/clang/lib/Basic/CMakeLists.txt
@@ -78,6 +78,7 @@ add_clang_library(clangBasic
   Targets/Hexagon.cpp
   Targets/Lanai.cpp
   Targets/Le64.cpp
+  Targets/M68k.cpp
   Targets/MSP430.cpp
   Targets/Mips.cpp
   Targets/NVPTX.cpp

diff  --git a/clang/lib/Basic/Targets.cpp b/clang/lib/Basic/Targets.cpp
index 159af12a90fa..793a471194fe 100644
--- a/clang/lib/Basic/Targets.cpp
+++ b/clang/lib/Basic/Targets.cpp
@@ -22,6 +22,7 @@
 #include "Targets/Hexagon.h"
 #include "Targets/Lanai.h"
 #include "Targets/Le64.h"
+#include "Targets/M68k.h"
 #include "Targets/MSP430.h"
 #include "Targets/Mips.h"
 #include "Targets/NVPTX.h"
@@ -303,6 +304,16 @@ TargetInfo *AllocateTarget(const llvm::Triple &Triple,
       return new MipsTargetInfo(Triple, Opts);
     }
 
+  case llvm::Triple::m68k:
+    switch (os) {
+    case llvm::Triple::Linux:
+      return new LinuxTargetInfo<M68kTargetInfo>(Triple, Opts);
+    case llvm::Triple::NetBSD:
+      return new NetBSDTargetInfo<M68kTargetInfo>(Triple, Opts);
+    default:
+      return new M68kTargetInfo(Triple, Opts);
+    }
+
   case llvm::Triple::le32:
     switch (os) {
     case llvm::Triple::NaCl:

diff  --git a/clang/lib/Basic/Targets/M68k.cpp 
b/clang/lib/Basic/Targets/M68k.cpp
new file mode 100644
index 000000000000..e10fd77d2590
--- /dev/null
+++ b/clang/lib/Basic/Targets/M68k.cpp
@@ -0,0 +1,168 @@
+//===--- M68k.cpp - Implement M68k targets feature support-------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements M68k TargetInfo objects.
+//
+//===----------------------------------------------------------------------===//
+
+#include "M68k.h"
+#include "clang/Basic/Builtins.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/TargetBuiltins.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/Support/TargetParser.h"
+#include <cstring>
+
+namespace clang {
+namespace targets {
+
+M68kTargetInfo::M68kTargetInfo(const llvm::Triple &Triple,
+                               const TargetOptions &)
+    : TargetInfo(Triple) {
+
+  std::string Layout = "";
+
+  // M68k is Big Endian
+  Layout += "E";
+
+  // FIXME how to wire it with the used object format?
+  Layout += "-m:e";
+
+  // M68k pointers are always 32 bit wide even for 16 bit cpus
+  Layout += "-p:32:32";
+
+  // M68k integer data types
+  Layout += "-i8:8:8-i16:16:16-i32:16:32";
+
+  // FIXME no floats at the moment
+
+  // The registers can hold 8, 16, 32 bits
+  Layout += "-n8:16:32";
+
+  // 16 bit alignment for both stack and aggregate
+  // in order to conform to ABI used by GCC
+  Layout += "-a:0:16-S16";
+
+  resetDataLayout(Layout);
+
+  SizeType = UnsignedInt;
+  PtrDiffType = SignedInt;
+  IntPtrType = SignedInt;
+}
+
+bool M68kTargetInfo::setCPU(const std::string &Name) {
+  StringRef N = Name;
+  CPU = llvm::StringSwitch<CPUKind>(N)
+            .Case("generic", CK_68000)
+            .Case("M68000", CK_68000)
+            .Case("M68010", CK_68010)
+            .Case("M68020", CK_68020)
+            .Case("M68030", CK_68030)
+            .Case("M68040", CK_68040)
+            .Case("M68060", CK_68060)
+            .Default(CK_Unknown);
+  return CPU != CK_Unknown;
+}
+
+void M68kTargetInfo::getTargetDefines(const LangOptions &Opts,
+                                      MacroBuilder &Builder) const {
+  using llvm::Twine;
+
+  Builder.defineMacro("__m68k__");
+
+  Builder.defineMacro("mc68000");
+  Builder.defineMacro("__mc68000");
+  Builder.defineMacro("__mc68000__");
+
+  // For sub-architecture
+  switch (CPU) {
+  case CK_68010:
+    Builder.defineMacro("mc68010");
+    Builder.defineMacro("__mc68010");
+    Builder.defineMacro("__mc68010__");
+    break;
+  case CK_68020:
+    Builder.defineMacro("mc68020");
+    Builder.defineMacro("__mc68020");
+    Builder.defineMacro("__mc68020__");
+    break;
+  case CK_68030:
+    Builder.defineMacro("mc68030");
+    Builder.defineMacro("__mc68030");
+    Builder.defineMacro("__mc68030__");
+    break;
+  case CK_68040:
+    Builder.defineMacro("mc68040");
+    Builder.defineMacro("__mc68040");
+    Builder.defineMacro("__mc68040__");
+    break;
+  case CK_68060:
+    Builder.defineMacro("mc68060");
+    Builder.defineMacro("__mc68060");
+    Builder.defineMacro("__mc68060__");
+    break;
+  default:
+    break;
+  }
+}
+
+ArrayRef<Builtin::Info> M68kTargetInfo::getTargetBuiltins() const {
+  // FIXME: Implement.
+  return None;
+}
+
+bool M68kTargetInfo::hasFeature(StringRef Feature) const {
+  // FIXME elaborate moar
+  return Feature == "M68000";
+}
+
+const char *const M68kTargetInfo::GCCRegNames[] = {
+    "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7",
+    "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7",
+    "pc"};
+
+ArrayRef<const char *> M68kTargetInfo::getGCCRegNames() const {
+  return llvm::makeArrayRef(GCCRegNames);
+}
+
+ArrayRef<TargetInfo::GCCRegAlias> M68kTargetInfo::getGCCRegAliases() const {
+  // No aliases.
+  return None;
+}
+
+bool M68kTargetInfo::validateAsmConstraint(
+    const char *&Name, TargetInfo::ConstraintInfo &info) const {
+  switch (*Name) {
+  case 'a': // address register
+  case 'd': // data register
+  case 'f': // floating point register
+    info.setAllowsRegister();
+    return true;
+  case 'K': // the constant 1
+  case 'L': // constant -1^20 .. 1^19
+  case 'M': // constant 1-4:
+    return true;
+  }
+  // FIXME: Support all constraints like 'N', 'O', 'P', 'R'
+  return false;
+}
+
+const char *M68kTargetInfo::getClobbers() const {
+  // FIXME: Is this really right?
+  return "";
+}
+
+M68kTargetInfo::BuiltinVaListKind M68kTargetInfo::getBuiltinVaListKind() const 
{
+  // FIXME: implement
+  llvm_unreachable("Not implemented yet");
+}
+
+} // namespace targets
+} // namespace clang

diff  --git a/clang/lib/Basic/Targets/M68k.h b/clang/lib/Basic/Targets/M68k.h
new file mode 100644
index 000000000000..db001be76c65
--- /dev/null
+++ b/clang/lib/Basic/Targets/M68k.h
@@ -0,0 +1,57 @@
+//===--- M68k.h - Declare M68k target feature support -------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares M68k TargetInfo objects.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_BASIC_TARGETS_M68K_H
+#define LLVM_CLANG_LIB_BASIC_TARGETS_M68K_H
+
+#include "OSTargets.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/TargetOptions.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/Support/Compiler.h"
+
+namespace clang {
+namespace targets {
+
+class LLVM_LIBRARY_VISIBILITY M68kTargetInfo : public TargetInfo {
+  static const char *const GCCRegNames[];
+
+  enum CPUKind {
+    CK_Unknown,
+    CK_68000,
+    CK_68010,
+    CK_68020,
+    CK_68030,
+    CK_68040,
+    CK_68060
+  } CPU = CK_Unknown;
+
+public:
+  M68kTargetInfo(const llvm::Triple &Triple, const TargetOptions &);
+
+  void getTargetDefines(const LangOptions &Opts,
+                        MacroBuilder &Builder) const override;
+  ArrayRef<Builtin::Info> getTargetBuiltins() const override;
+  bool hasFeature(StringRef Feature) const override;
+  ArrayRef<const char *> getGCCRegNames() const override;
+  ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override;
+  bool validateAsmConstraint(const char *&Name,
+                             TargetInfo::ConstraintInfo &info) const override;
+  const char *getClobbers() const override;
+  BuiltinVaListKind getBuiltinVaListKind() const override;
+  bool setCPU(const std::string &Name) override;
+};
+
+} // namespace targets
+} // namespace clang
+
+#endif

diff  --git a/clang/lib/CodeGen/TargetInfo.cpp 
b/clang/lib/CodeGen/TargetInfo.cpp
index 8c3857ff268b..f4427967da9f 100644
--- a/clang/lib/CodeGen/TargetInfo.cpp
+++ b/clang/lib/CodeGen/TargetInfo.cpp
@@ -8049,6 +8049,43 @@ 
MIPSTargetCodeGenInfo::initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF,
   return false;
 }
 
+//===----------------------------------------------------------------------===//
+// M68k ABI Implementation
+//===----------------------------------------------------------------------===//
+
+namespace {
+
+class M68kTargetCodeGenInfo : public TargetCodeGenInfo {
+public:
+  M68kTargetCodeGenInfo(CodeGenTypes &CGT)
+      : TargetCodeGenInfo(std::make_unique<DefaultABIInfo>(CGT)) {}
+  void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
+                           CodeGen::CodeGenModule &M) const override;
+};
+
+} // namespace
+
+void M68kTargetCodeGenInfo::setTargetAttributes(
+    const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &M) const {
+  if (const auto *FD = dyn_cast_or_null<FunctionDecl>(D)) {
+    if (const auto *attr = FD->getAttr<M68kInterruptAttr>()) {
+      // Handle 'interrupt' attribute:
+      llvm::Function *F = cast<llvm::Function>(GV);
+
+      // Step 1: Set ISR calling convention.
+      F->setCallingConv(llvm::CallingConv::M68k_INTR);
+
+      // Step 2: Add attributes goodness.
+      F->addFnAttr(llvm::Attribute::NoInline);
+
+      // Step 3: Emit ISR vector alias.
+      unsigned Num = attr->getNumber() / 2;
+      llvm::GlobalAlias::create(llvm::Function::ExternalLinkage,
+                                "__isr_" + Twine(Num), F);
+    }
+  }
+}
+
 
//===----------------------------------------------------------------------===//
 // AVR ABI Implementation.
 
//===----------------------------------------------------------------------===//
@@ -10876,6 +10913,8 @@ const TargetCodeGenInfo 
&CodeGenModule::getTargetCodeGenInfo() {
 
   case llvm::Triple::le32:
     return SetCGInfo(new PNaClTargetCodeGenInfo(Types));
+  case llvm::Triple::m68k:
+    return SetCGInfo(new M68kTargetCodeGenInfo(Types));
   case llvm::Triple::mips:
   case llvm::Triple::mipsel:
     if (Triple.getOS() == llvm::Triple::NaCl)

diff  --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index 7ca5c2fb9c1c..4376342185fb 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -6641,6 +6641,39 @@ static void handleMipsInterruptAttr(Sema &S, Decl *D, 
const ParsedAttr &AL) {
   D->addAttr(::new (S.Context) MipsInterruptAttr(S.Context, AL, Kind));
 }
 
+static void handleM68kInterruptAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+  if (!checkAttributeNumArgs(S, AL, 1))
+    return;
+
+  if (!AL.isArgExpr(0)) {
+    S.Diag(AL.getLoc(), diag::err_attribute_argument_type)
+        << AL << AANT_ArgumentIntegerConstant;
+    return;
+  }
+
+  // FIXME: Check for decl - it should be void ()(void).
+
+  Expr *NumParamsExpr = static_cast<Expr *>(AL.getArgAsExpr(0));
+  auto MaybeNumParams = NumParamsExpr->getIntegerConstantExpr(S.Context);
+  if (!MaybeNumParams) {
+    S.Diag(AL.getLoc(), diag::err_attribute_argument_type)
+        << AL << AANT_ArgumentIntegerConstant
+        << NumParamsExpr->getSourceRange();
+    return;
+  }
+
+  unsigned Num = MaybeNumParams->getLimitedValue(255);
+  if ((Num & 1) || Num > 30) {
+    S.Diag(AL.getLoc(), diag::err_attribute_argument_out_of_bounds)
+        << AL << (int)MaybeNumParams->getSExtValue()
+        << NumParamsExpr->getSourceRange();
+    return;
+  }
+
+  D->addAttr(::new (S.Context) M68kInterruptAttr(S.Context, AL, Num));
+  D->addAttr(UsedAttr::CreateImplicit(S.Context));
+}
+
 static void handleAnyX86InterruptAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
   // Semantic checks for a function with the 'interrupt' attribute.
   // a) Must be a function.
@@ -6913,6 +6946,9 @@ static void handleInterruptAttr(Sema &S, Decl *D, const 
ParsedAttr &AL) {
   case llvm::Triple::mips:
     handleMipsInterruptAttr(S, D, AL);
     break;
+  case llvm::Triple::m68k:
+    handleM68kInterruptAttr(S, D, AL);
+    break;
   case llvm::Triple::x86:
   case llvm::Triple::x86_64:
     handleAnyX86InterruptAttr(S, D, AL);


        
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to