Skip to content

Commit

Permalink
[LLD] Adding EVM architecture to LLD.
Browse files Browse the repository at this point in the history
  • Loading branch information
PavelKopyl committed Sep 25, 2024
1 parent d30dbf5 commit 2ce379f
Show file tree
Hide file tree
Showing 6 changed files with 109 additions and 0 deletions.
94 changes: 94 additions & 0 deletions lld/ELF/Arch/EVM.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
//===- EVM.cpp ------------------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// EVM is a stack-based virtual machine with a word size of 256 bits intendent
// for execution of smart contracts in Ethereum blockchain environment.
//
// Since it is a baremetal programming, there's usually no loader to load
// ELF files on EVMs. You are expected to link your program against address
// 0 and pull out a .text section from the result using objcopy, so that you
// can write the linked code to on-chip flush memory. You can do that with
// the following commands:
//
// ld.lld -Ttext=0 -o foo foo.o
// objcopy -O binary --only-section=.text foo output.bin
//
//===----------------------------------------------------------------------===//

#include "InputFiles.h"
#include "Symbols.h"
#include "Target.h"
#include "lld/Common/ErrorHandler.h"
#include "llvm/BinaryFormat/ELF.h"
#include "llvm/Support/Endian.h"

using namespace llvm;
using namespace llvm::object;
using namespace llvm::support::endian;
using namespace llvm::ELF;
using namespace lld;
using namespace lld::elf;

namespace {
class EVM final : public TargetInfo {
public:
uint32_t calcEFlags() const override;
RelExpr getRelExpr(RelType type, const Symbol &s,
const uint8_t *loc) const override;
void relocate(uint8_t *loc, const Relocation &rel,
uint64_t val) const override;
};
} // namespace

RelExpr EVM::getRelExpr(RelType type, const Symbol &s,
const uint8_t *loc) const {
switch (type) {
case R_EVM_DATA:
return R_ABS;
default:
error(getErrorLocation(loc) + "unknown relocation (" + Twine(type) +
") against symbol " + toString(s));
return R_NONE;
}
}

void EVM::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
switch (rel.type) {
case R_EVM_DATA: {
if (val > std::numeric_limits<uint32_t>::max())
llvm_unreachable("R_EVM_DATA: to big relocation value");
write32be(loc, val);
break;
}
default:
llvm_unreachable("unknown relocation");
}
}

TargetInfo *elf::getEVMTargetInfo() {
static EVM target;
return &target;
}

static uint32_t getEFlags(InputFile *file) {
return cast<ObjFile<ELF32LE>>(file)->getObj().getHeader().e_flags;
}

uint32_t EVM::calcEFlags() const {
assert(!ctx.objectFiles.empty());

const uint32_t flags = getEFlags(ctx.objectFiles[0]);
for (InputFile *f : ArrayRef(ctx.objectFiles).slice(1)) {
const uint32_t objFlags = getEFlags(f);
if ((objFlags /* & EF_EVM_ARCH_MASK*/) != (flags /* & EF_EVM_ARCH_MASK*/))
error(toString(f) +
": cannot link object files with incompatible target ISA");
}

return flags;
}
1 change: 1 addition & 0 deletions lld/ELF/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ add_lld_library(lldELF
Arch/AMDGPU.cpp
Arch/ARM.cpp
Arch/AVR.cpp
Arch/EVM.cpp
Arch/EraVM.cpp
Arch/Hexagon.cpp
Arch/LoongArch.cpp
Expand Down
3 changes: 3 additions & 0 deletions lld/ELF/Driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@
#include "llvm/Config/llvm-config.h"
#include "llvm/LTO/LTO.h"
#include "llvm/Object/Archive.h"
// EVM local begin
#include "llvm/Object/ELF.h"
// EVM local end
#include "llvm/Remarks/HotnessThresholdParser.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Compression.h"
Expand Down
4 changes: 4 additions & 0 deletions lld/ELF/InputFiles.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1614,6 +1614,10 @@ static uint16_t getBitcodeMachineKind(StringRef path, const Triple &t) {
return t.isOSIAMCU() ? EM_IAMCU : EM_386;
case Triple::x86_64:
return EM_X86_64;
// EVM local begin
case Triple::evm:
return EM_EVM;
// EVM local end
default:
error(path + ": could not infer e_machine from bitcode target triple " +
t.str());
Expand Down
4 changes: 4 additions & 0 deletions lld/ELF/Target.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,10 @@ TargetInfo *elf::getTarget() {
return getSPARCV9TargetInfo();
case EM_X86_64:
return getX86_64TargetInfo();
// EVM local begin
case EM_EVM:
return getEVMTargetInfo();
// EVM local end
}
llvm_unreachable("unknown target machine");
}
Expand Down
3 changes: 3 additions & 0 deletions lld/ELF/Target.h
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,9 @@ TargetInfo *getRISCVTargetInfo();
TargetInfo *getSPARCV9TargetInfo();
TargetInfo *getX86TargetInfo();
TargetInfo *getX86_64TargetInfo();
// EVM local begin
TargetInfo *getEVMTargetInfo();
// EVM local end
template <class ELFT> TargetInfo *getMipsTargetInfo();

struct ErrorPlace {
Expand Down

0 comments on commit 2ce379f

Please sign in to comment.