Skip to content

Commit

Permalink
[EraVM] Split assembler syntax for direct/indirect code references.
Browse files Browse the repository at this point in the history
1. code[@symbol + reg + imm]
   Denotes indirect code reference. Loads a word from the code page
   at the offset (measured in words): "@symbol + reg + imm".

2. @symbol + imm
   Just denotes the expression value itself. @symbol is resolved
   as an offset to the label measured in instructions.
add @.OUTLINED_FUNCTION_RET2[0], r0, stack[-1]
  • Loading branch information
PavelKopyl authored and akiramenai committed Aug 13, 2024
1 parent 32d817b commit 8bf1e55
Show file tree
Hide file tree
Showing 76 changed files with 550 additions and 566 deletions.
2 changes: 1 addition & 1 deletion lld/test/ELF/eravm-binary-layout.s
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

.text
nop stack+=[2 + r0]
add @glob_initializer[0], r0, stack[@glob]
add code[@glob_initializer], r0, stack[@glob]

.globl get_glob
get_glob:
Expand Down
10 changes: 5 additions & 5 deletions lld/test/ELF/eravm-code-reloc.s
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ foo_local:
caller_g:
near_call r1, @foo, @handler
far_call r3, r4, @foo
add @.OUTLINED_FUNCTION_RET0[0], r0, stack-[1]
add @.OUTLINED_FUNCTION_RET0, r0, stack-[1]
jump @foo_local
.OUTLINED_FUNCTION_RET0:
jump @label
Expand All @@ -77,15 +77,15 @@ caller_g:
ret.panic.to_label @label
.globl label
label:
jump @jump_table[1]
jump code[@jump_table + 1]
ret
; INPUT-LABEL: <caller_g>:
; INPUT-NEXT: 00 00 00 00 00 01 04 0f near_call r1, 0, 0
; INPUT-NEXT: R_ERAVM_16_SCALE_8 handler
; INPUT-NEXT: R_ERAVM_16_SCALE_8 foo
; INPUT-NEXT: 00 00 00 00 00 43 04 21 far_call r3, r4, 0
; INPUT-NEXT: R_ERAVM_16_SCALE_8 foo
; INPUT-NEXT: 00 01 00 00 00 00 00 45 add code[0], r0, stack-[1 + r0]
; INPUT-NEXT: 00 01 00 00 00 00 00 3d add 0, r0, stack-[1 + r0]
; INPUT-NEXT: R_ERAVM_16_SCALE_8 .text+0x40
; INPUT-NEXT: 00 00 00 00 00 00 01 3d jump 0
; INPUT-NEXT: R_ERAVM_16_SCALE_8 .text+0x18
Expand All @@ -105,7 +105,7 @@ label:
; OUTPUT-LABEL: <caller_g>:
; OUTPUT-NEXT: 00 12 00 13 00 01 04 0f near_call r1, 19, 18
; OUTPUT-NEXT: 00 00 00 13 00 43 04 21 far_call r3, r4, 19
; OUTPUT-NEXT: 00 01 00 18 00 00 00 45 add code[24], r0, stack-[1 + r0]
; OUTPUT-NEXT: 00 01 00 18 00 00 00 3d add 24, r0, stack-[1 + r0]
; OUTPUT-NEXT: 00 00 00 13 00 00 01 3d jump 19
; OUTPUT-NEXT: 00 00 00 1c 00 00 01 3d jump 28
; OUTPUT-NEXT: 00 00 00 1c 00 01 04 2e ret.ok.to_label r1, 28
Expand All @@ -127,7 +127,7 @@ caller_l:
ret.panic.to_label @label_local
.local label_local
label_local:
jump @jump_table_local[1]
jump code[@jump_table_local + 1]
ret

; INPUT-LABEL: <caller_l>:
Expand Down
16 changes: 8 additions & 8 deletions lld/test/ELF/eravm-data-reloc.s
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,9 @@ array_const_local:
.text
.p2align 3
reloc_src_g:
add @scalar_const[0], r1, r1
add code[@scalar_const], r1, r1
add stack[@scalar_var], r1, r1
add @array_const[1], r1, r1
add code[@array_const + 1], r1, r1
add stack[@array_var + 1], r1, r1
ret
; INPUT-LABEL: <reloc_src_g>:
Expand All @@ -99,9 +99,9 @@ reloc_src_g:
; OUTPUT-NEXT: 00 00 00 00 00 01 04 2d ret

reloc_src_l:
add @scalar_const_local[0], r1, r1
add code[@scalar_const_local], r1, r1
add stack[@scalar_var_local], r1, r1
add @array_const_local[1], r1, r1
add code[@array_const_local + 1], r1, r1
add stack[@array_var_local + 1], r1, r1
ret
; INPUT-LABEL: <reloc_src_l>:
Expand Down Expand Up @@ -155,9 +155,9 @@ reloc_dst_l:
; OUTPUT-NEXT: 00 00 00 00 00 01 04 2d ret

reloc_both_g:
add @scalar_const[0], r1, stack[@array_var + 1]
add code[@scalar_const], r1, stack[@array_var + 1]
add stack[@scalar_var], r1, stack[@array_var + 1]
add @array_const[1], r1, stack[@scalar_var]
add code[@array_const + 1], r1, stack[@scalar_var]
add stack[@array_var + 1], r1, stack[@scalar_var]
ret
; INPUT-LABEL: <reloc_both_g>:
Expand All @@ -183,9 +183,9 @@ reloc_both_g:
; OUTPUT-NEXT: 00 00 00 00 00 01 04 2d ret

reloc_both_l:
add @scalar_const_local[0], r1, stack[@array_var_local + 1]
add code[@scalar_const_local], r1, stack[@array_var_local + 1]
add stack[@scalar_var_local], r1, stack[@array_var_local + 1]
add @array_const_local[1], r1, stack[@scalar_var_local]
add code[@array_const_local + 1], r1, stack[@scalar_var_local]
add stack[@array_var_local + 1], r1, stack[@scalar_var_local]
ret
; INPUT-LABEL: <reloc_both_l>:
Expand Down
126 changes: 62 additions & 64 deletions llvm/lib/Target/EraVM/AsmParser/EraVMAsmParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ class EraVMAsmParser : public MCTargetAsmParser {
bool parseRegOperand(OperandVector &Operands);
OperandMatchResultTy tryParseUImm16Operand(OperandVector &Operands);
OperandMatchResultTy tryParseJumpTargetOperand(OperandVector &Operands);
bool parseAddend(int &Addend, bool SignRequired);
bool parseRegisterWithAddend(MCRegister &RegNo, MCSymbol *&Symbol,
int &Addend);
bool parseOperand(StringRef Mnemonic, OperandVector &Operands);
Expand Down Expand Up @@ -418,6 +419,31 @@ bool EraVMAsmParser::parseRegOperand(OperandVector &Operands) {

OperandMatchResultTy
EraVMAsmParser::tryParseUImm16Operand(OperandVector &Operands) {
// First check if this is a symbol + addend.
if (getTok().is(AsmToken::At)) {
MCSymbol *Symbol = nullptr;
SMLoc StartOfOperand = getLexer().getLoc();
int Addend = 0;

Lex(); // eat "@" token
Symbol = getContext().getOrCreateSymbol(getTok().getString());
Lex(); // eat symbol name
if (getTok().is(AsmToken::Plus) || getTok().is(AsmToken::Minus))
if (parseAddend(Addend, /*SignRequired=*/true))
return MatchOperand_ParseFail;

const MCExpr *Expr = MCSymbolRefExpr::create(Symbol, getContext());
// FIXME Should we support negative addends?
Addend &= (unsigned)0xffff;
if (Addend) {
const MCExpr *AddendExpr = createConstant(Addend);
Expr = MCBinaryExpr::createAdd(Expr, AddendExpr, getContext());
}
Operands.push_back(
EraVMOperand::CreateImm(Expr, StartOfOperand, getTok().getEndLoc()));
return MatchOperand_Success;
}

if (getLexer().is(AsmToken::Minus) &&
getLexer().peekTok().is(AsmToken::Integer)) {
TokError("negative immediate operands are not supported");
Expand Down Expand Up @@ -462,34 +488,33 @@ EraVMAsmParser::tryParseJumpTargetOperand(OperandVector &Operands) {
return MatchOperand_Success;
}

bool EraVMAsmParser::parseRegisterWithAddend(MCRegister &RegNo,
MCSymbol *&Symbol, int &Addend) {
auto ParseAddend = [this, &Addend](bool SignRequired) {
int Multiplier = 1;

switch (getTok().getKind()) {
case AsmToken::Plus:
Multiplier = 1;
Lex(); // eat "+" token
break;
case AsmToken::Minus:
Multiplier = -1;
Lex(); // eat "-" token
break;
default:
if (SignRequired)
return TokError("'+' or '-' expected");
break;
}
bool EraVMAsmParser::parseAddend(int &Addend, bool SignRequired) {
int Multiplier = 1;
switch (getTok().getKind()) {
case AsmToken::Plus:
Multiplier = 1;
Lex(); // eat "+" token
break;
case AsmToken::Minus:
Multiplier = -1;
Lex(); // eat "-" token
break;
default:
if (SignRequired)
return TokError("'+' or '-' expected");
break;
}

if (!getLexer().is(AsmToken::Integer))
return TokError("integer addend expected");
Addend = Multiplier * getTok().getIntVal();
Lex(); // eat integer token
if (!getLexer().is(AsmToken::Integer))
return TokError("integer addend expected");
Addend = Multiplier * getTok().getIntVal();
Lex(); // eat integer token

return false;
};
return false;
}

bool EraVMAsmParser::parseRegisterWithAddend(MCRegister &RegNo,
MCSymbol *&Symbol, int &Addend) {
auto ParseRegister = [this, &RegNo]() {
SMLoc S, E;
if (tryParseRegister(RegNo, S, E))
Expand Down Expand Up @@ -529,10 +554,10 @@ bool EraVMAsmParser::parseRegisterWithAddend(MCRegister &RegNo,
return true;
if (getTok().is(AsmToken::RBrac))
return false; // keep "]" token for the caller
return ParseAddend(/*SignRequired=*/true);
return parseAddend(Addend, /*SignRequired=*/true);
}

if (ParseAddend(/*SignRequired=*/false))
if (parseAddend(Addend, /*SignRequired=*/false))
return true;
if (getTok().is(AsmToken::RBrac))
return false; // keep "]" token for the caller
Expand Down Expand Up @@ -633,33 +658,18 @@ EraVMAsmParser::tryParseStackOperand(OperandVector &Operands) {
OperandMatchResultTy
EraVMAsmParser::tryParseCodeOperand(OperandVector &Operands) {
SMLoc StartOfOperand = getLexer().getLoc();
MCSymbol *Symbol = nullptr;
MCSymbol *SymbolInSubscript = nullptr;
MCRegister RegNo = 0;
int Addend = 0;

// Decide if this is a code operand
SmallVector<AsmToken, 2> PeekedTokens(2);
getLexer().peekTokens(PeekedTokens);
if (getTok().is(AsmToken::At)) {
// "@symbol_name[...]"
if (!PeekedTokens[0].is(AsmToken::Identifier) ||
!PeekedTokens[1].is(AsmToken::LBrac))
return MatchOperand_NoMatch;

Lex(); // eat "@" token
Symbol = getContext().getOrCreateSymbol(getTok().getString());
Lex(); // eat constant symbol name
Lex(); // eat "[" token
} else {
// "code[...]"
if (!getTok().is(AsmToken::Identifier) ||
!PeekedTokens[0].is(AsmToken::LBrac) || getTok().getString() != "code")
return MatchOperand_NoMatch;
// "code[...]"
if (!getTok().is(AsmToken::Identifier) ||
!getLexer().peekTok().is(AsmToken::LBrac) ||
getTok().getString() != "code")
return MatchOperand_NoMatch;

Lex(); // eat "code" token
Lex(); // eat "[" token
}
Lex(); // eat "code" token
Lex(); // eat "[" token

if (parseRegisterWithAddend(RegNo, SymbolInSubscript, Addend))
return MatchOperand_ParseFail;
Expand All @@ -670,21 +680,9 @@ EraVMAsmParser::tryParseCodeOperand(OperandVector &Operands) {
if (parseToken(AsmToken::RBrac, "']' expected"))
return MatchOperand_ParseFail;

if (Symbol) {
// @symbol_name[reg + imm]
if (SymbolInSubscript) {
Error(StartOfOperand, "two symbols in a single operand");
return MatchOperand_ParseFail;
}
Operands.push_back(EraVMOperand::CreateMem(
&getContext(), EraVM::OperandCode, RegNo, Symbol, Addend,
StartOfOperand, getTok().getEndLoc()));
} else {
// code[...]
Operands.push_back(EraVMOperand::CreateMem(
&getContext(), EraVM::OperandCode, RegNo, SymbolInSubscript, Addend,
StartOfOperand, getTok().getEndLoc()));
}
Operands.push_back(EraVMOperand::CreateMem(
&getContext(), EraVM::OperandCode, RegNo, SymbolInSubscript, Addend,
StartOfOperand, getTok().getEndLoc()));

return MatchOperand_Success;
}
Expand Down
3 changes: 1 addition & 2 deletions llvm/lib/Target/EraVM/EraVMInstrInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1125,9 +1125,8 @@ MachineBasicBlock::iterator EraVMInstrInfo::insertOutlinedCall(
It->setPostInstrSymbol(MF, RetSym);

// Add instruction to store return address onto the top of the stack.
BuildMI(MBB, It, DL, get(EraVM::ADDcrs_s))
BuildMI(MBB, It, DL, get(EraVM::ADDirs_s))
.addSym(RetSym, EraVMII::MO_SYM_RET_ADDRESS)
.addImm(0 /* RetSymOffset */)
.addReg(EraVM::R0)
.addReg(EraVM::SP)
.addImm(0 /* AMBase2 */)
Expand Down
26 changes: 1 addition & 25 deletions llvm/lib/Target/EraVM/MCTargetDesc/EraVMELFObjectWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,32 +39,8 @@ class EraVMELFObjectWriter : public MCELFObjectTargetWriter {
const MCFixup &Fixup, bool IsPCRel) const override {
// Translate fixup kind to ELF relocation type.
switch (Fixup.getTargetKind()) {
case EraVM::fixup_16_scale_32: {
// There may be cases where the relocation symbol is in the code,
// for example:
//
// add @.OUTLINED_FUNCTION_RET0[0], r0, stack-[1]
// jump @OUTLINED_FUNCTION_0
// .OUTLINED_FUNCTION_RET0:
// jump.ge @.BB1_16
// jump @.BB1_23
//
// Here the .OUTLINED_FUNCTION_RET0[0] represents the code offset,
// measured in 8-byte units.
// In such cases the actual relocation type should be R_ERAVM_16_SCALE_8.
if (const MCSymbolRefExpr *A = Target.getSymA()) {
const MCSymbol &Sym = A->getSymbol();
assert(Sym.isDefined());
MCSection &Section = Sym.getSection();
const MCSectionELF *SectionELF = dyn_cast<MCSectionELF>(&Section);
assert(SectionELF && "Null section for reloc symbol");

unsigned Flags = SectionELF->getFlags();
if ((Flags & ELF::SHF_ALLOC) && (Flags & ELF::SHF_EXECINSTR))
return ELF::R_ERAVM_16_SCALE_8;
}
case EraVM::fixup_16_scale_32:
return ELF::R_ERAVM_16_SCALE_32;
}
case EraVM::fixup_16_scale_8:
return ELF::R_ERAVM_16_SCALE_8;
default:
Expand Down
19 changes: 11 additions & 8 deletions llvm/lib/Target/EraVM/MCTargetDesc/EraVMInstPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -114,25 +114,28 @@ void EraVMInstPrinter::printMemOperand(const MCInst *MI, unsigned OpNo,
if (BaseReg == EraVM::R0)
BaseReg = 0;

if (Symbol)
O << "@" << Symbol->getName() << "[";
else
O << "code[";
O << "code[";

if (!BaseReg && !Addend)
O << "0";
if (Symbol)
O << "@" << Symbol->getName();

if (BaseReg)
if (BaseReg) {
if (Symbol)
O << "+";
O << getRegisterName(BaseReg);
}

if (Addend) {
if (Addend < 0)
O << "-";
else if (BaseReg)
else if (Symbol || BaseReg)
O << "+";
O << std::abs(Addend);
}

if (!Symbol && !BaseReg && !Addend)
O << "0";

O << "]";
}

Expand Down
7 changes: 7 additions & 0 deletions llvm/lib/Target/EraVM/MCTargetDesc/EraVMMCCodeEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,13 @@ EraVMMCCodeEmitter::getMachineOpValue(const MCInst &MI, const MCOperand &MO,
return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg());
if (MO.isImm())
return MO.getImm();
if (MO.isExpr()) {
// This corresponds to the cases where the operand
// is an expression of the form: @symbol + imm.
auto FK = static_cast<MCFixupKind>(EraVM::fixup_16_scale_8);
Fixups.push_back(MCFixup::create(2, MO.getExpr(), FK, MI.getLoc()));
return 0;
}

llvm_unreachable("Unexpected generic operand type");
}
Expand Down
4 changes: 2 additions & 2 deletions llvm/test/CodeGen/EraVM/add.ll
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ define i256 @addirr(i256 %rs1) nounwind {

; CHECK-LABEL: addcrr
define i256 @addcrr(i256 %rs1) nounwind {
; CHECK: add @val[0], r1, r1
; CHECK: add code[@val], r1, r1
%val = load i256, i256 addrspace(4)* @val
%res = add i256 %rs1, %val
ret i256 %res
Expand Down Expand Up @@ -57,7 +57,7 @@ define void @addirs(i256 %rs1) nounwind {
; CHECK-LABEL: addcrs
define void @addcrs(i256 %rs1) nounwind {
%valptr = alloca i256
; CHECK: add @val[0], r1, stack-[1]
; CHECK: add code[@val], r1, stack-[1]
%val = load i256, i256 addrspace(4)* @val
%res = add i256 %rs1, %val
store i256 %res, i256* %valptr
Expand Down
Loading

0 comments on commit 8bf1e55

Please sign in to comment.