Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
135 changes: 134 additions & 1 deletion llvm/lib/Target/Xtensa/AsmParser/XtensaAsmParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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"

Expand All @@ -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;
Copy link
Contributor

Choose a reason for hiding this comment

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

This method is deprecated, use parseDirective (starting with lowercase letter).

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

bool parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) override;
bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
SMLoc NameLoc, OperandVector &Operands) override;
Expand All @@ -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"
Expand All @@ -62,6 +74,7 @@ class XtensaAsmParser : public MCTargetAsmParser {
return ParseStatus::NoMatch;
}
ParseStatus parsePCRelTarget(OperandVector &Operands);
bool parseLiteralDirective(SMLoc L);

public:
enum XtensaMatchResultTy {
Expand Down Expand Up @@ -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) &&
Expand Down Expand Up @@ -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;
Copy link
Contributor

Choose a reason for hiding this comment

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

Formatting is off, break before brace

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

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,
Expand All @@ -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;
Expand Down Expand Up @@ -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;
Copy link
Contributor

Choose a reason for hiding this comment

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

The method should consume the terminating newline.

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

}

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;
Copy link
Contributor

Choose a reason for hiding this comment

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

Parse the newline.

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

}

if (IDVal == ".literal") {
parseLiteralDirective(Loc);
Lex();
return false;
}

return true;
}

// Force static initialization.
extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeXtensaAsmParser() {
RegisterMCAsmParser<XtensaAsmParser> X(getTheXtensaTarget());
Expand Down
3 changes: 3 additions & 0 deletions llvm/lib/Target/Xtensa/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ 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)
Expand All @@ -15,13 +16,15 @@ add_public_tablegen_target(XtensaCommonTableGen)

add_llvm_target(XtensaCodeGen
XtensaAsmPrinter.cpp
XtensaConstantPoolValue.cpp
XtensaFrameLowering.cpp
XtensaInstrInfo.cpp
XtensaISelDAGToDAG.cpp
XtensaISelLowering.cpp
XtensaRegisterInfo.cpp
XtensaSubtarget.cpp
XtensaTargetMachine.cpp
XtensaUtils.cpp

LINK_COMPONENTS
AsmPrinter
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/Target/Xtensa/MCTargetDesc/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ add_llvm_component_library(LLVMXtensaDesc
XtensaMCCodeEmitter.cpp
XtensaMCExpr.cpp
XtensaMCTargetDesc.cpp
XtensaTargetStreamer.cpp

LINK_COMPONENTS
MC
Expand Down
26 changes: 24 additions & 2 deletions llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCTargetDesc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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(),
Expand All @@ -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);
}
87 changes: 87 additions & 0 deletions llvm/lib/Target/Xtensa/MCTargetDesc/XtensaTargetStreamer.cpp
Original file line number Diff line number Diff line change
@@ -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();
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
MCSectionELF *CS = (MCSectionELF *)OutStreamer.getCurrentSectionOnly();
auto *CS = static_cast<MCSectionELF *>OutStreamer.getCurrentSectionOnly();

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

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);
}
Loading