Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Xtensa] Initial codegen support from IR #78548

Merged
merged 1 commit into from
Feb 12, 2024

Conversation

andreisfr
Copy link
Contributor

@andreisfr andreisfr commented Jan 18, 2024

This PR provides implementation of the basic codegen infra such as TargetFrameLowering, MCInstLower,
AsmPrinter, RegisterInfo, InstructionInfo, TargetLowering, SelectionDAGISel.

Migrated from https://reviews.llvm.org/D145658

Copy link

Thank you for submitting a Pull Request (PR) to the LLVM Project!

This PR will be automatically labeled and the relevant teams will be
notified.

If you wish to, you can add reviewers by using the "Reviewers" section on this page.

If this is not working for you, it is probably because you do not have write
permissions for the repository. In which case you can instead tag reviewers by
name in a comment by using @ followed by their GitHub username.

If you have received no comments on your PR for a week, you can request a review
by "ping"ing the PR by adding a comment “Ping”. The common courtesy "ping" rate
is once a week. Please remember that you are asking for valuable time from other developers.

If you have further questions, they may be answered by the LLVM GitHub User Guide.

You can also ask questions in a comment on this PR, on the LLVM Discord or on the forums.

@llvmbot llvmbot added the mc Machine (object) code label Jan 18, 2024
@llvmbot
Copy link
Collaborator

llvmbot commented Jan 18, 2024

@llvm/pr-subscribers-mc

Author: Andrei Safronov (andreisfr)

Changes

This PR provides implementation of the basic codegen infra such as TargetFrameLowering, CallingConv, TargetLowering, SelectionDAGISe. Initial ConstantPool support has also been implemented.

The PR contains five commits that were originally published on Phabricator (third patch is approved), each commit depends on previous commits, and together these patches provide support for more complex IR tests. Patches have been updated based on reviewers comments from Phabricator and slightly refactored.

Migrated from:
https://reviews.llvm.org/D145658
https://reviews.llvm.org/D145660
https://reviews.llvm.org/D145661 (this Differential is approved in Phabricator)
https://reviews.llvm.org/D145662
https://reviews.llvm.org/D145663


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

42 Files Affected:

  • (modified) llvm/lib/Target/Xtensa/AsmParser/XtensaAsmParser.cpp (+134-1)
  • (modified) llvm/lib/Target/Xtensa/CMakeLists.txt (+13)
  • (modified) llvm/lib/Target/Xtensa/MCTargetDesc/CMakeLists.txt (+1)
  • (modified) llvm/lib/Target/Xtensa/MCTargetDesc/XtensaAsmBackend.cpp (+1-1)
  • (modified) llvm/lib/Target/Xtensa/MCTargetDesc/XtensaInstPrinter.cpp (+4-4)
  • (modified) llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCCodeEmitter.cpp (+3-3)
  • (modified) llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCExpr.cpp (+1-1)
  • (modified) llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCTargetDesc.cpp (+24-2)
  • (added) llvm/lib/Target/Xtensa/MCTargetDesc/XtensaTargetStreamer.cpp (+87)
  • (added) llvm/lib/Target/Xtensa/MCTargetDesc/XtensaTargetStreamer.h (+46)
  • (added) llvm/lib/Target/Xtensa/Xtensa.h (+30)
  • (modified) llvm/lib/Target/Xtensa/Xtensa.td (+6)
  • (added) llvm/lib/Target/Xtensa/XtensaAsmPrinter.cpp (+183)
  • (added) llvm/lib/Target/Xtensa/XtensaAsmPrinter.h (+46)
  • (added) llvm/lib/Target/Xtensa/XtensaCallingConv.td (+30)
  • (added) llvm/lib/Target/Xtensa/XtensaConstantPoolValue.cpp (+210)
  • (added) llvm/lib/Target/Xtensa/XtensaConstantPoolValue.h (+267)
  • (added) llvm/lib/Target/Xtensa/XtensaFrameLowering.cpp (+44)
  • (added) llvm/lib/Target/Xtensa/XtensaFrameLowering.h (+34)
  • (added) llvm/lib/Target/Xtensa/XtensaISelDAGToDAG.cpp (+130)
  • (added) llvm/lib/Target/Xtensa/XtensaISelLowering.cpp (+429)
  • (added) llvm/lib/Target/Xtensa/XtensaISelLowering.h (+76)
  • (added) llvm/lib/Target/Xtensa/XtensaInstrInfo.cpp (+96)
  • (added) llvm/lib/Target/Xtensa/XtensaInstrInfo.h (+62)
  • (modified) llvm/lib/Target/Xtensa/XtensaInstrInfo.td (+10-1)
  • (added) llvm/lib/Target/Xtensa/XtensaMCInstLower.cpp (+110)
  • (added) llvm/lib/Target/Xtensa/XtensaMCInstLower.h (+50)
  • (modified) llvm/lib/Target/Xtensa/XtensaOperands.td (+1-1)
  • (added) llvm/lib/Target/Xtensa/XtensaOperators.td (+23)
  • (added) llvm/lib/Target/Xtensa/XtensaRegisterInfo.cpp (+118)
  • (added) llvm/lib/Target/Xtensa/XtensaRegisterInfo.h (+60)
  • (added) llvm/lib/Target/Xtensa/XtensaSubtarget.cpp (+46)
  • (added) llvm/lib/Target/Xtensa/XtensaSubtarget.h (+72)
  • (modified) llvm/lib/Target/Xtensa/XtensaTargetMachine.cpp (+28-2)
  • (modified) llvm/lib/Target/Xtensa/XtensaTargetMachine.h (+6)
  • (added) llvm/lib/Target/Xtensa/XtensaUtils.cpp (+60)
  • (added) llvm/lib/Target/Xtensa/XtensaUtils.h (+27)
  • (added) llvm/test/CodeGen/Xtensa/alu.ll (+158)
  • (added) llvm/test/CodeGen/Xtensa/constantpool.ll (+80)
  • (added) llvm/test/CodeGen/Xtensa/stack-access.ll (+36)
  • (modified) llvm/test/MC/Xtensa/Core/invalid.s (-4)
  • (added) llvm/test/MC/Xtensa/directive-literal.s (+42)
diff --git a/llvm/lib/Target/Xtensa/AsmParser/XtensaAsmParser.cpp b/llvm/lib/Target/Xtensa/AsmParser/XtensaAsmParser.cpp
index 3f808298527f8fc..9fd05ee96a9290d 100644
--- a/llvm/lib/Target/Xtensa/AsmParser/XtensaAsmParser.cpp
+++ b/llvm/lib/Target/Xtensa/AsmParser/XtensaAsmParser.cpp
@@ -8,7 +8,9 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "MCTargetDesc/XtensaMCExpr.h"
 #include "MCTargetDesc/XtensaMCTargetDesc.h"
+#include "MCTargetDesc/XtensaTargetStreamer.h"
 #include "TargetInfo/XtensaTargetInfo.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/StringSwitch.h"
@@ -22,6 +24,7 @@
 #include "llvm/MC/MCRegisterInfo.h"
 #include "llvm/MC/MCStreamer.h"
 #include "llvm/MC/MCSubtargetInfo.h"
+#include "llvm/MC/MCSymbol.h"
 #include "llvm/MC/TargetRegistry.h"
 #include "llvm/Support/Casting.h"
 
@@ -35,6 +38,12 @@ class XtensaAsmParser : public MCTargetAsmParser {
 
   SMLoc getLoc() const { return getParser().getTok().getLoc(); }
 
+  XtensaTargetStreamer &getTargetStreamer() {
+    MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
+    return static_cast<XtensaTargetStreamer &>(TS);
+  }
+
+  bool ParseDirective(AsmToken DirectiveID) override;
   bool parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) override;
   bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
                         SMLoc NameLoc, OperandVector &Operands) override;
@@ -45,6 +54,9 @@ class XtensaAsmParser : public MCTargetAsmParser {
   unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
                                       unsigned Kind) override;
 
+  bool processInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
+                          const MCSubtargetInfo *STI);
+
 // Auto-generated instruction matching functions
 #define GET_ASSEMBLER_HEADER
 #include "XtensaGenAsmMatcher.inc"
@@ -62,6 +74,7 @@ class XtensaAsmParser : public MCTargetAsmParser {
     return ParseStatus::NoMatch;
   }
   ParseStatus parsePCRelTarget(OperandVector &Operands);
+  bool parseLiteralDirective(SMLoc L);
 
 public:
   enum XtensaMatchResultTy {
@@ -148,7 +161,13 @@ struct XtensaOperand : public MCParsedAsmOperand {
 
   bool isImm12() const { return isImm(-2048, 2047); }
 
-  bool isImm12m() const { return isImm(-2048, 2047); }
+  // Convert MOVI to literal load, when immediate is not in range (-2048, 2047)
+  bool isImm12m() const {
+    if (Kind == Immediate)
+      return true;
+
+    return false;
+  }
 
   bool isOffset4m32() const {
     return isImm(0, 60) &&
@@ -348,6 +367,67 @@ static SMLoc RefineErrorLoc(const SMLoc Loc, const OperandVector &Operands,
   return Loc;
 }
 
+bool XtensaAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
+                                         MCStreamer &Out,
+                                         const MCSubtargetInfo *STI) {
+  Inst.setLoc(IDLoc);
+  const unsigned Opcode = Inst.getOpcode();
+  switch (Opcode) {
+  case Xtensa::L32R: {
+    const MCSymbolRefExpr *OpExpr =
+        (const MCSymbolRefExpr *)Inst.getOperand(1).getExpr();
+    XtensaMCExpr::VariantKind Kind = XtensaMCExpr::VK_Xtensa_None;
+    const MCExpr *NewOpExpr = XtensaMCExpr::create(OpExpr, Kind, getContext());
+    Inst.getOperand(1).setExpr(NewOpExpr);
+  } break;
+  case Xtensa::MOVI: {
+    XtensaTargetStreamer &TS = this->getTargetStreamer();
+
+    // Expand MOVI operand
+    if (!Inst.getOperand(1).isExpr()) {
+      uint64_t ImmOp64 = Inst.getOperand(1).getImm();
+      int32_t Imm = ImmOp64;
+      if ((Imm < -2048) || (Imm > 2047)) {
+        XtensaTargetStreamer &TS = this->getTargetStreamer();
+        MCInst TmpInst;
+        TmpInst.setLoc(IDLoc);
+        TmpInst.setOpcode(Xtensa::L32R);
+        const MCExpr *Value = MCConstantExpr::create(ImmOp64, getContext());
+        MCSymbol *Sym = getContext().createTempSymbol();
+        const MCExpr *Expr = MCSymbolRefExpr::create(
+            Sym, MCSymbolRefExpr::VK_None, getContext());
+        const MCExpr *OpExpr = XtensaMCExpr::create(
+            Expr, XtensaMCExpr::VK_Xtensa_None, getContext());
+        TmpInst.addOperand(Inst.getOperand(0));
+        MCOperand Op1 = MCOperand::createExpr(OpExpr);
+        TmpInst.addOperand(Op1);
+        TS.emitLiteral(Sym, Value, IDLoc);
+        Inst = TmpInst;
+      }
+    } else {
+      MCInst TmpInst;
+      TmpInst.setLoc(IDLoc);
+      TmpInst.setOpcode(Xtensa::L32R);
+      const MCExpr *Value = Inst.getOperand(1).getExpr();
+      MCSymbol *Sym = getContext().createTempSymbol();
+      const MCExpr *Expr =
+          MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
+      const MCExpr *OpExpr = XtensaMCExpr::create(
+          Expr, XtensaMCExpr::VK_Xtensa_None, getContext());
+      TmpInst.addOperand(Inst.getOperand(0));
+      MCOperand Op1 = MCOperand::createExpr(OpExpr);
+      TmpInst.addOperand(Op1);
+      Inst = TmpInst;
+      TS.emitLiteral(Sym, Value, IDLoc);
+    }
+  } break;
+  default:
+    break;
+  }
+
+  return true;
+}
+
 bool XtensaAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
                                               OperandVector &Operands,
                                               MCStreamer &Out,
@@ -361,6 +441,7 @@ bool XtensaAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
   default:
     break;
   case Match_Success:
+    processInstruction(Inst, IDLoc, Out, STI);
     Inst.setLoc(IDLoc);
     Out.emitInstruction(Inst, getSTI());
     return false;
@@ -686,6 +767,58 @@ bool XtensaAsmParser::ParseInstruction(ParseInstructionInfo &Info,
   return false;
 }
 
+bool XtensaAsmParser::parseLiteralDirective(SMLoc L) {
+  MCAsmParser &Parser = getParser();
+  MCSymbol *Sym;
+  const MCExpr *Value;
+  SMLoc LiteralLoc = getLexer().getLoc();
+  XtensaTargetStreamer &TS = this->getTargetStreamer();
+
+  if (Parser.parseExpression(Value))
+    return true;
+
+  const MCSymbolRefExpr *SE = dyn_cast<MCSymbolRefExpr>(Value);
+  if (!SE)
+    return Error(LiteralLoc, "literal label must be a symbol");
+  else {
+    Sym = getContext().getOrCreateSymbol(SE->getSymbol().getName());
+  }
+
+  if (Parser.parseToken(AsmToken::Comma, "expected comma"))
+    return true;
+
+  SMLoc OpcodeLoc = getLexer().getLoc();
+  if (parseOptionalToken(AsmToken::EndOfStatement))
+    return Error(OpcodeLoc, "expected value");
+
+  if (Parser.parseExpression(Value))
+    return true;
+
+  TS.emitLiteral(Sym, Value, LiteralLoc);
+
+  return false;
+}
+
+bool XtensaAsmParser::ParseDirective(AsmToken DirectiveID) {
+  StringRef IDVal = DirectiveID.getString();
+  SMLoc Loc = getLexer().getLoc();
+
+  if (IDVal == ".literal_position") {
+    XtensaTargetStreamer &TS = this->getTargetStreamer();
+    TS.emitLiteralPosition();
+    Lex();
+    return false;
+  }
+
+  if (IDVal == ".literal") {
+    parseLiteralDirective(Loc);
+    Lex();
+    return false;
+  }
+
+  return true;
+}
+
 // Force static initialization.
 extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeXtensaAsmParser() {
   RegisterMCAsmParser<XtensaAsmParser> X(getTheXtensaTarget());
diff --git a/llvm/lib/Target/Xtensa/CMakeLists.txt b/llvm/lib/Target/Xtensa/CMakeLists.txt
index 7192f7392072b31..f0abf3e550a124e 100644
--- a/llvm/lib/Target/Xtensa/CMakeLists.txt
+++ b/llvm/lib/Target/Xtensa/CMakeLists.txt
@@ -4,6 +4,8 @@ set(LLVM_TARGET_DEFINITIONS Xtensa.td)
 
 tablegen(LLVM XtensaGenAsmMatcher.inc -gen-asm-matcher)
 tablegen(LLVM XtensaGenAsmWriter.inc -gen-asm-writer)
+tablegen(LLVM XtensaGenCallingConv.inc -gen-callingconv)
+tablegen(LLVM XtensaGenDAGISel.inc -gen-dag-isel)
 tablegen(LLVM XtensaGenDisassemblerTables.inc -gen-disassembler)
 tablegen(LLVM XtensaGenInstrInfo.inc -gen-instr-info)
 tablegen(LLVM XtensaGenMCCodeEmitter.inc -gen-emitter)
@@ -13,13 +15,24 @@ tablegen(LLVM XtensaGenSubtargetInfo.inc -gen-subtarget)
 add_public_tablegen_target(XtensaCommonTableGen)
 
 add_llvm_target(XtensaCodeGen
+  XtensaAsmPrinter.cpp
+  XtensaConstantPoolValue.cpp
+  XtensaFrameLowering.cpp
+  XtensaInstrInfo.cpp
+  XtensaISelDAGToDAG.cpp
+  XtensaISelLowering.cpp
+  XtensaMCInstLower.cpp
+  XtensaRegisterInfo.cpp
+  XtensaSubtarget.cpp
   XtensaTargetMachine.cpp
+  XtensaUtils.cpp
 
   LINK_COMPONENTS
   AsmPrinter
   CodeGen
   Core
   MC
+  SelectionDAG
   Support
   Target
   XtensaDesc
diff --git a/llvm/lib/Target/Xtensa/MCTargetDesc/CMakeLists.txt b/llvm/lib/Target/Xtensa/MCTargetDesc/CMakeLists.txt
index 6841b44f9d569cd..dc12863394c7ad0 100644
--- a/llvm/lib/Target/Xtensa/MCTargetDesc/CMakeLists.txt
+++ b/llvm/lib/Target/Xtensa/MCTargetDesc/CMakeLists.txt
@@ -6,6 +6,7 @@ add_llvm_component_library(LLVMXtensaDesc
   XtensaMCCodeEmitter.cpp
   XtensaMCExpr.cpp
   XtensaMCTargetDesc.cpp
+  XtensaTargetStreamer.cpp
 
   LINK_COMPONENTS
   MC
diff --git a/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaAsmBackend.cpp b/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaAsmBackend.cpp
index db4484bb57c1ad7..c87e2187b73d4e6 100644
--- a/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaAsmBackend.cpp
+++ b/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaAsmBackend.cpp
@@ -84,7 +84,7 @@ static uint64_t adjustFixupValue(const MCFixup &Fixup, uint64_t Value,
   unsigned Kind = Fixup.getKind();
   switch (Kind) {
   default:
-    llvm_unreachable("Unknown fixup kind!");
+    report_fatal_error("Unknown fixup kind!");
   case FK_Data_1:
   case FK_Data_2:
   case FK_Data_4:
diff --git a/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaInstPrinter.cpp b/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaInstPrinter.cpp
index fe1dc0e2e483e72..f234d5e900a472a 100644
--- a/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaInstPrinter.cpp
+++ b/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaInstPrinter.cpp
@@ -102,7 +102,7 @@ void XtensaInstPrinter::printBranchTarget(const MCInst *MI, int OpNum,
   } else if (MC.isExpr())
     MC.getExpr()->print(OS, &MAI, true);
   else
-    llvm_unreachable("Invalid operand");
+    report_fatal_error("Invalid operand");
 }
 
 void XtensaInstPrinter::printJumpTarget(const MCInst *MI, int OpNum,
@@ -117,7 +117,7 @@ void XtensaInstPrinter::printJumpTarget(const MCInst *MI, int OpNum,
   } else if (MC.isExpr())
     MC.getExpr()->print(OS, &MAI, true);
   else
-    llvm_unreachable("Invalid operand");
+    report_fatal_error("Invalid operand");
   ;
 }
 
@@ -133,7 +133,7 @@ void XtensaInstPrinter::printCallOperand(const MCInst *MI, int OpNum,
   } else if (MC.isExpr())
     MC.getExpr()->print(OS, &MAI, true);
   else
-    llvm_unreachable("Invalid operand");
+    report_fatal_error("Invalid operand");
 }
 
 void XtensaInstPrinter::printL32RTarget(const MCInst *MI, int OpNum,
@@ -151,7 +151,7 @@ void XtensaInstPrinter::printL32RTarget(const MCInst *MI, int OpNum,
   } else if (MC.isExpr())
     MC.getExpr()->print(O, &MAI, true);
   else
-    llvm_unreachable("Invalid operand");
+    report_fatal_error("Invalid operand");
 }
 
 void XtensaInstPrinter::printImm8_AsmOperand(const MCInst *MI, int OpNum,
diff --git a/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCCodeEmitter.cpp b/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCCodeEmitter.cpp
index 1afdbb38f9571a2..c6941499cba192d 100644
--- a/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCCodeEmitter.cpp
+++ b/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCCodeEmitter.cpp
@@ -203,7 +203,7 @@ XtensaMCCodeEmitter::getCallEncoding(const MCInst &MI, unsigned int OpNum,
   if (MO.isImm()) {
     int32_t Res = MO.getImm();
     if (Res & 0x3) {
-      llvm_unreachable("Unexpected operand value!");
+      report_fatal_error("Unexpected operand value!");
     }
     Res >>= 2;
     return Res;
@@ -396,7 +396,7 @@ XtensaMCCodeEmitter::getB4constOpValue(const MCInst &MI, unsigned OpNo,
     Res = 15;
     break;
   default:
-    llvm_unreachable("Unexpected operand value!");
+    report_fatal_error("Unexpected operand value!");
   }
 
   return Res;
@@ -446,7 +446,7 @@ XtensaMCCodeEmitter::getB4constuOpValue(const MCInst &MI, unsigned OpNo,
     Res = 15;
     break;
   default:
-    llvm_unreachable("Unexpected operand value!");
+    report_fatal_error("Unexpected operand value!");
   }
 
   return Res;
diff --git a/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCExpr.cpp b/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCExpr.cpp
index cafd8b7e2978202..2d0db1aae0645b3 100644
--- a/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCExpr.cpp
+++ b/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCExpr.cpp
@@ -58,6 +58,6 @@ XtensaMCExpr::VariantKind XtensaMCExpr::getVariantKindForName(StringRef name) {
 StringRef XtensaMCExpr::getVariantKindName(VariantKind Kind) {
   switch (Kind) {
   default:
-    llvm_unreachable("Invalid ELF symbol kind");
+    report_fatal_error("Invalid ELF symbol kind");
   }
 }
diff --git a/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCTargetDesc.cpp b/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCTargetDesc.cpp
index 48674d15bdfbe27..8914ebf658cc434 100644
--- a/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCTargetDesc.cpp
+++ b/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCTargetDesc.cpp
@@ -10,6 +10,7 @@
 #include "XtensaMCTargetDesc.h"
 #include "XtensaInstPrinter.h"
 #include "XtensaMCAsmInfo.h"
+#include "XtensaTargetStreamer.h"
 #include "TargetInfo/XtensaTargetInfo.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/MC/MCAsmInfo.h"
@@ -63,16 +64,29 @@ createXtensaMCSubtargetInfo(const Triple &TT, StringRef CPU, StringRef FS) {
   return createXtensaMCSubtargetInfoImpl(TT, CPU, CPU, FS);
 }
 
+static MCTargetStreamer *
+createXtensaAsmTargetStreamer(MCStreamer &S, formatted_raw_ostream &OS,
+                              MCInstPrinter *InstPrint, bool isVerboseAsm) {
+  return new XtensaTargetAsmStreamer(S, OS);
+}
+
+static MCTargetStreamer *
+createXtensaObjectTargetStreamer(MCStreamer &S, const MCSubtargetInfo &STI) {
+  return new XtensaTargetELFStreamer(S);
+}
+
 extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeXtensaTargetMC() {
   // Register the MCAsmInfo.
-  TargetRegistry::RegisterMCAsmInfo(getTheXtensaTarget(), createXtensaMCAsmInfo);
+  TargetRegistry::RegisterMCAsmInfo(getTheXtensaTarget(),
+                                    createXtensaMCAsmInfo);
 
   // Register the MCCodeEmitter.
   TargetRegistry::RegisterMCCodeEmitter(getTheXtensaTarget(),
                                         createXtensaMCCodeEmitter);
 
   // Register the MCInstrInfo.
-  TargetRegistry::RegisterMCInstrInfo(getTheXtensaTarget(), createXtensaMCInstrInfo);
+  TargetRegistry::RegisterMCInstrInfo(getTheXtensaTarget(),
+                                      createXtensaMCInstrInfo);
 
   // Register the MCInstPrinter.
   TargetRegistry::RegisterMCInstPrinter(getTheXtensaTarget(),
@@ -89,4 +103,12 @@ extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeXtensaTargetMC() {
   // Register the MCAsmBackend.
   TargetRegistry::RegisterMCAsmBackend(getTheXtensaTarget(),
                                        createXtensaMCAsmBackend);
+
+  // Register the asm target streamer.
+  TargetRegistry::RegisterAsmTargetStreamer(getTheXtensaTarget(),
+                                            createXtensaAsmTargetStreamer);
+
+  // Register the ELF target streamer.
+  TargetRegistry::RegisterObjectTargetStreamer(
+      getTheXtensaTarget(), createXtensaObjectTargetStreamer);
 }
diff --git a/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaTargetStreamer.cpp b/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaTargetStreamer.cpp
new file mode 100644
index 000000000000000..4163e64de48f091
--- /dev/null
+++ b/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaTargetStreamer.cpp
@@ -0,0 +1,87 @@
+//===-- XtensaTargetStreamer.cpp - Xtensa Target Streamer Methods ---------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// 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 provides Xtensa specific target streamer methods.
+//
+//===----------------------------------------------------------------------===//
+
+#include "XtensaTargetStreamer.h"
+#include "XtensaInstPrinter.h"
+#include "llvm/BinaryFormat/ELF.h"
+#include "llvm/MC/MCAssembler.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCObjectFileInfo.h"
+#include "llvm/MC/MCSectionELF.h"
+#include "llvm/Support/FormattedStream.h"
+
+using namespace llvm;
+
+XtensaTargetStreamer::XtensaTargetStreamer(MCStreamer &S)
+    : MCTargetStreamer(S) {}
+
+XtensaTargetAsmStreamer::XtensaTargetAsmStreamer(MCStreamer &S,
+                                                 formatted_raw_ostream &OS)
+    : XtensaTargetStreamer(S), OS(OS) {}
+
+void XtensaTargetAsmStreamer::emitLiteral(MCSymbol *LblSym, const MCExpr *Value,
+                                          SMLoc L) {
+  const MCAsmInfo *MAI = Streamer.getContext().getAsmInfo();
+
+  OS << "\t.literal\t";
+  LblSym->print(OS, MAI);
+  OS << ", ";
+  Value->print(OS, MAI);
+  OS << '\n';
+}
+
+void XtensaTargetAsmStreamer::emitLiteralPosition() {
+  OS << "\t.literal_position\n";
+}
+
+XtensaTargetELFStreamer::XtensaTargetELFStreamer(MCStreamer &S)
+    : XtensaTargetStreamer(S) {}
+
+static std::string getLiteralSectionName(std::string CSectionName) {
+  std::size_t Pos = CSectionName.find(".text");
+  std::string SectionName;
+  if (Pos != std::string::npos) {
+    if (Pos > 0)
+      SectionName = CSectionName.substr(0, Pos + 5);
+    else
+      SectionName = "";
+    SectionName += ".literal";
+    SectionName += CSectionName.substr(Pos + 5);
+  } else {
+    SectionName = CSectionName;
+    SectionName += ".literal";
+  }
+  return SectionName;
+}
+
+void XtensaTargetELFStreamer::emitLiteral(MCSymbol *LblSym, const MCExpr *Value,
+                                          SMLoc L) {
+  MCContext &Context = getStreamer().getContext();
+  MCStreamer &OutStreamer = getStreamer();
+  MCSectionELF *CS = (MCSectionELF *)OutStreamer.getCurrentSectionOnly();
+  std::string SectionName = getLiteralSectionName(CS->getName().str());
+
+  MCSection *ConstSection = Context.getELFSection(
+      SectionName, ELF::SHT_PROGBITS, ELF::SHF_EXECINSTR | ELF::SHF_ALLOC);
+
+  OutStreamer.pushSection();
+  OutStreamer.switchSection(ConstSection);
+  OutStreamer.emitLabel(LblSym, L);
+  OutStreamer.emitValue(Value, 4, L);
+  OutStreamer.popSection();
+}
+
+MCELFStreamer &XtensaTargetELFStreamer::getStreamer() {
+  return static_cast<MCELFStreamer &>(Streamer);
+}
diff --git a/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaTargetStreamer.h b/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaTargetStreamer.h
new file mode 100644
index 000000000000000..a7d8b6dd9c792b5
--- /dev/null
+++ b/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaTargetStreamer.h
@@ -0,0 +1,46 @@
+//===-- XtensaTargetStreamer.h - Xtensa Target Streamer --------*- C++ -*--===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_TARGET_XTENSA_XTENSATARGETSTREAMER_H
+#define LLVM_LIB_TARGET_XTENSA_XTENSATARGETSTREAMER_H
+
+#include "llvm/MC/MCELFStreamer.h"
+#include "llvm/MC/MCStreamer.h"
+#include "llvm/Support/SMLoc.h"
+
+namespace llvm {
+class formatted_raw_ostream;
+
+class XtensaTargetStreamer : public MCTargetStreamer {
+public:
+  XtensaTargetStreamer(MCStreamer &S);
+  virtual void emitLiteral(MCSymbol *LblSym, const MCExpr *Value, SMLoc L) = 0;
+  virtual void emitLiteralPosition() = 0;
+};
+
+class XtensaTargetAsmStreamer : public XtensaTargetStreamer {
+  formatted_raw_ostream &OS;
+
+public:
+  XtensaTargetAsmStreamer(MCStreamer &S, formatted_raw_ostream &OS);
+  void emitLiteral(MCSymbol *LblSym, const MCExpr *Value, SMLoc L) override;
+  void emitLiteralPosition() override;
+};
+
+class XtensaTargetELFStreamer : public XtensaTargetStreamer {
+public:
+  XtensaTargetELFStreamer(MCStreamer &S);
+  MCELFStreamer &getStreamer();
+  void emitLiteral(MCSymbol *LblSym, const MCExpr *Value, SMLoc L) override;
+  void emitLiteralPosition() override {}
+};
+} // end namespace llvm
+
+#endif
diff --git a/llvm/lib/Target/Xtensa/Xtensa.h b/llvm/lib/Target/Xtensa/Xtensa.h
new file mode...
[truncated]

Copy link

github-actions bot commented Jan 18, 2024

✅ With the latest revision this PR passed the C/C++ code formatter.

@arsenm
Copy link
Contributor

arsenm commented Jan 18, 2024

Unfortunately you should open a separate PR for each of these changes

Copy link
Contributor

@s-barannikov s-barannikov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Calling convention implementation needs to be in separate PR. It should support passing arguments on the stack, which requires implementing some methods in *FrameLowering, *InstrInfo and *RegisterInfo, as well as supporting load/store/call/return in ISel.

I would also suggest a separate PR for boilerplate classes, i.e. *RegisterInfo, *InstrInfo, *Subtarget, *FrameLowering, *TargetMachine, *AsmPrinter and *DAGToDAGISel. You can check that everything works by launching llc on an empty *.ll file (it should produce a template assembly (-filetype=asm) and object (-filetype=obj) files without crashing).

Supporting ALU operations should then touch only files related to instruction selection. (There may be other minor changes in other files.)

Changes in MCTargetDesc/ look completely unrelated.

@andreisfr andreisfr changed the title [Xtensa] Initial support of the ALU operations and ConstantPool [Xtensa] Initial support of the ALU operation Jan 22, 2024
@andreisfr
Copy link
Contributor Author

Calling convention implementation needs to be in separate PR. It should support passing arguments on the stack, which requires implementing some methods in *FrameLowering, *InstrInfo and *RegisterInfo, as well as supporting load/store/call/return in ISel.

I would also suggest a separate PR for boilerplate classes, i.e. *RegisterInfo, *InstrInfo, *Subtarget, *FrameLowering, *TargetMachine, *AsmPrinter and *DAGToDAGISel. You can check that everything works by launching llc on an empty *.ll file (it should produce a template assembly (-filetype=asm) and object (-filetype=obj) files without crashing).

Supporting ALU operations should then touch only files related to instruction selection. (There may be other minor changes in other files.)

Changes in MCTargetDesc/ look completely unrelated.

Thanks for the comment. Do I understand correctly that you are proposing to split this patch into three patches (the last one will be with ALU operations)?

@s-barannikov
Copy link
Contributor

Yes, that's what I'm proposing.

@andreisfr andreisfr force-pushed the xtensa_alu_codegen branch 3 times, most recently from 074c148 to 45525f6 Compare January 26, 2024 23:12
@andreisfr andreisfr changed the title [Xtensa] Initial support of the ALU operation [Xtensa] Initial codegen support from IR Jan 26, 2024
@andreisfr
Copy link
Contributor Author

andreisfr commented Jan 26, 2024

Yes, that's what I'm proposing.

Thank you. I removed the Calling Convention functionality from this commit and will prepare a separate patch with it.

@andreisfr
Copy link
Contributor Author

andreisfr commented Jan 26, 2024

Unfortunately you should open a separate PR for each of these changes

Thanks, I removed redundant commits.

@MaskRay
Copy link
Member

MaskRay commented Feb 2, 2024

git log -- llvm/lib/Target/M68k/ M68k from 2021 sets a good example for new ports. You may follow it:)

I think the patch series https://reviews.llvm.org/D145658 may be too fine-grained. It might be better to pack more changes in one PR, otherwise there could be a lot of -Wunused-private-field and not many testable units.

For CMake changes, I always check the first two of the following configurations. A -DBUILD_SHARED_LIBS=on build, thanks to -Wl,-z,defs, can catch a lot of missing dependencies.

default
-DBUILD_SHARED_LIBS=on
-DLLVM_LINK_LLVM_DYLIB=on
(asan) -DLLVM_USE_SANITIZER=Address -DLLVM_ENABLE_RUNTIMES=


XtensaSubtarget::XtensaSubtarget(const Triple &TT, const std::string &CPU,
const std::string &FS, const TargetMachine &TM)
: XtensaGenSubtargetInfo(TT, CPU, /*TuneCPU*/ CPU, FS), TargetTriple(TT),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Canonical style is /*TuneCPU=*/CPU

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you very much for comments. Fixed

class XtensaSubtarget;
class XtensaInstrInfo : public XtensaGenInstrInfo {
const XtensaRegisterInfo RI;
XtensaSubtarget &STI;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please ensure that each incremental change does not cause new warnings when compiled with a recent Clang.

You may use https://raw.githubusercontent.com/chromium/chromium/main/tools/clang/scripts/update.py

warning: private field 'STI' is not used [-Wunused-private-field]

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed, I implemented "getSubtarget()" function.

class XtensaAsmPrinter;

class LLVM_LIBRARY_VISIBILITY XtensaMCInstLower {
MCContext &Ctx;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: private field 'Ctx' is not used [-Wunused-private-field]

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fxied.

Copy link
Contributor

@arsenm arsenm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm with some nits

Comment on lines 31 to 33
// hasFP - Return true if the specified function should have a dedicated frame
// pointer register. This is true if the function has variable sized allocas or
// if frame pointer elimination is disabled.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wouldn't bother duplicating the base implementation comment here

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you very much for comments. Fixed

}

const char *XtensaTargetLowering::getTargetNodeName(unsigned Opcode) const {
return NULL;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nullptr

Copy link
Contributor Author

@andreisfr andreisfr Feb 7, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

int SPAdj, unsigned FIOperandNum,
RegScavenger *RS) const {
report_fatal_error("Eliminate frame index not supported yet");
return false;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dead return

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed


Register XtensaRegisterInfo::getFrameRegister(const MachineFunction &MF) const {
const TargetFrameLowering *TFI = MF.getSubtarget().getFrameLowering();
return TFI->hasFP(MF) ? (Xtensa::A15) : Xtensa::SP;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No () around register name.

Also should do getSubtarget()

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

@gerekon
Copy link

gerekon commented Feb 6, 2024

@MaskRay sorry for bothering you. I am from Espressif LLVM team.

I think the patch series https://reviews.llvm.org/D145658 may be too fine-grained. It might be better to pack more changes in one PR, otherwise there could be a lot of -Wunused-private-field and not many testable units.

Looks like this conflicts with suggestions from @s-barannikov #78548 (review). As far as I understood he proposed to split it into more fine-grained commits.
Or I miss smth?

@arsenm
Copy link
Contributor

arsenm commented Feb 6, 2024

@MaskRay sorry for bothering you. I am from Espressif LLVM team.

I think the patch series https://reviews.llvm.org/D145658 may be too fine-grained. It might be better to pack more changes in one PR, otherwise there could be a lot of -Wunused-private-field and not many testable units.

Looks like this conflicts with suggestions from @s-barannikov #78548 (review). As far as I understood he proposed to split it into more fine-grained commits. Or I miss smth?

The split is better to review, but the pieces should build warning free and come with the relevant tests. I think this patch is fine with the warnings fixed

Copy link
Contributor

@s-barannikov s-barannikov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM with comments in XtensaTargetMachine.h addressed.

llvm/lib/Target/Xtensa/Xtensa.h Outdated Show resolved Hide resolved
llvm/lib/Target/Xtensa/XtensaMCInstLower.h Outdated Show resolved Hide resolved
llvm/lib/Target/Xtensa/XtensaMCInstLower.cpp Outdated Show resolved Hide resolved
llvm/lib/Target/Xtensa/XtensaRegisterInfo.h Show resolved Hide resolved
llvm/lib/Target/Xtensa/XtensaRegisterInfo.h Outdated Show resolved Hide resolved
llvm/lib/Target/Xtensa/XtensaSubtarget.h Outdated Show resolved Hide resolved
Comment on lines 47 to 49
XtensaSubtarget(const Triple &TT, const std::string &CPU,
const std::string &FS, const TargetMachine &TM);

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

const std::string & -> StringRef

TT parameter is redundant as it can be obtained from TM.

Copy link
Contributor Author

@andreisfr andreisfr Feb 7, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed "const std::string" problem. Do you mean we should use XtensaSubtarget constructor prototype without TT argument?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, but this is a very minor issue. Most backends do pass it.

llvm/lib/Target/Xtensa/XtensaTargetMachine.h Outdated Show resolved Hide resolved
llvm/lib/Target/Xtensa/XtensaTargetMachine.h Outdated Show resolved Hide resolved
llvm/lib/Target/Xtensa/XtensaAsmPrinter.cpp Outdated Show resolved Hide resolved
Copy link
Contributor

@s-barannikov s-barannikov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, final style nits

llvm/lib/Target/Xtensa/XtensaISelLowering.cpp Outdated Show resolved Hide resolved
llvm/lib/Target/Xtensa/XtensaInstrInfo.cpp Outdated Show resolved Hide resolved
llvm/lib/Target/Xtensa/XtensaInstrInfo.h Outdated Show resolved Hide resolved
llvm/lib/Target/Xtensa/XtensaTargetMachine.h Outdated Show resolved Hide resolved
Initial codegen support for IR tests. Added basic
implementation of the TargetFrameLowering, MCInstLower,
AsmPrinter, RegisterInfo, InstructionInfo,
TargetLowering, SelectionDAGISel.
@MaskRay
Copy link
Member

MaskRay commented Feb 9, 2024

I'll land this patch on your behalf tomorrow, unless someone objects it, assuming that you do not have write access yet!

@andreisfr
Copy link
Contributor Author

I'll land this patch on your behalf tomorrow, unless someone objects it, assuming that you do not have write access yet!

Thank you!

@sstefan1 sstefan1 merged commit b5046a7 into llvm:main Feb 12, 2024
3 of 4 checks passed
@gerekon
Copy link

gerekon commented Feb 16, 2024

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
mc Machine (object) code
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

7 participants