Skip to content

Commit c1b41f1

Browse files
bors[bot]vext01
andauthored
81: Start serialising our own Yk IR. r=ltratt a=vext01 Co-authored-by: Edd Barrett <[email protected]>
2 parents 8245ec3 + 0885f8a commit c1b41f1

File tree

10 files changed

+179
-5
lines changed

10 files changed

+179
-5
lines changed

llvm/include/llvm/CodeGen/AsmPrinter.h

+2
Original file line numberDiff line numberDiff line change
@@ -661,6 +661,8 @@ class AsmPrinter : public MachineFunctionPass {
661661
/// Emit a long long directive and value.
662662
void emitInt64(uint64_t Value) const;
663663

664+
void emitSizeT(uint64_t Value) const;
665+
664666
/// Emit something like ".long Hi-Lo" where the size in bytes of the directive
665667
/// is specified by Size and Hi/Lo specify the labels. This implicitly uses
666668
/// .set if it is available.

llvm/include/llvm/MC/MCStreamer.h

+1
Original file line numberDiff line numberDiff line change
@@ -743,6 +743,7 @@ class MCStreamer {
743743
void emitInt16(uint64_t Value) { emitIntValue(Value, 2); }
744744
void emitInt32(uint64_t Value) { emitIntValue(Value, 4); }
745745
void emitInt64(uint64_t Value) { emitIntValue(Value, 8); }
746+
void emitSizeT(uint64_t Value) { emitIntValue(Value, sizeof(size_t)); }
746747

747748
/// Special case of EmitValue that avoids the client having to pass
748749
/// in a MCExpr for constant integers & prints in Hex format for certain

llvm/include/llvm/YkIR/YkIRWriter.h

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#ifndef __YKIRWRITER_H
2+
#define __YKIRWRITER_H
3+
4+
#include "llvm/IR/Module.h"
5+
#include "llvm/MC/MCContext.h"
6+
#include "llvm/MC/MCStreamer.h"
7+
8+
namespace llvm {
9+
void embedYkIR(MCContext &Ctx, MCStreamer &OutStreamer, Module &M);
10+
} // namespace llvm
11+
12+
#endif

llvm/lib/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ add_subdirectory(XRay)
4444
if (LLVM_INCLUDE_TESTS)
4545
add_subdirectory(Testing)
4646
endif()
47+
add_subdirectory(YkIR)
4748
add_subdirectory(WindowsDriver)
4849
add_subdirectory(WindowsManifest)
4950

llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp

+12-4
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@
114114
#include "llvm/Target/TargetLoweringObjectFile.h"
115115
#include "llvm/Target/TargetMachine.h"
116116
#include "llvm/Target/TargetOptions.h"
117+
#include "llvm/YkIR/YkIRWriter.h"
117118
#include <algorithm>
118119
#include <cassert>
119120
#include <cinttypes>
@@ -137,6 +138,7 @@ static cl::opt<bool>
137138
extern bool YkAllocLLVMBBAddrMapSection;
138139
extern bool YkExtendedLLVMBBAddrMapSection;
139140
extern bool YkStackMapOffsetFix;
141+
extern bool YkEmbedIR;
140142

141143
const char DWARFGroupName[] = "dwarf";
142144
const char DWARFGroupDescription[] = "DWARF Emission";
@@ -2382,18 +2384,24 @@ bool AsmPrinter::doFinalization(Module &M) {
23822384
OutStreamer->popSection();
23832385
}
23842386

2385-
// The `embed-bitcode` flag serialises the IR after only architecture
2387+
// The `embed-bitcode` flag serialises the LLVM IR after only architecture
23862388
// agnostic optimisations have been run, but then proceeds to apply other
23872389
// optimisations and transformations afterwards. Sometimes this final version
2388-
// is precisely what we are interested in. The `embed-bitcode-final` flag
2389-
// waits until all optimisations/transformations have been run before
2390-
// embedding the IR.
2390+
// is precisely what we are interested in. The `embed-bitcode-final` and
2391+
// `yk-embed-ir` flags wait until all LLVM IR optimisations/transformations
2392+
// have been run before embedding their respective IR. Note that at the time
2393+
// of embedding, the MIR pipeline hasn't yet run, and this may do some more
2394+
// optimisation.
23912395
if (EmbedBitcodeFinal)
23922396
llvm::embedBitcodeInModule(M, llvm::MemoryBufferRef(),
23932397
/*EmbedBitcode*/ true,
23942398
/*EmbedCmdline*/ false,
23952399
/*CmdArgs*/ std::vector<uint8_t>());
23962400

2401+
if (YkEmbedIR) {
2402+
llvm::embedYkIR(OutContext, *OutStreamer, M);
2403+
}
2404+
23972405
// Set the MachineFunction to nullptr so that we can catch attempted
23982406
// accesses to MF specific features at the module level and so that
23992407
// we can conditionalize accesses based on whether or not it is nullptr.

llvm/lib/CodeGen/AsmPrinter/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -45,4 +45,5 @@ add_llvm_component_library(LLVMAsmPrinter
4545
Support
4646
Target
4747
TargetParser
48+
YkIR
4849
)

llvm/lib/Support/Yk.cpp

+15
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,20 @@ struct CreateYkOptNoneAfterIRPassesParser {
111111
static ManagedStatic<cl::opt<bool, true>,
112112
CreateYkOptNoneAfterIRPassesParser> YkOptNoneAfterIRPassesParser;
113113

114+
bool YkEmbedIR;
115+
namespace {
116+
struct CreateYkEmbedIRParser {
117+
static void *call() {
118+
return new cl::opt<bool, true>(
119+
"yk-embed-ir",
120+
cl::desc(
121+
"Embed Yk IR into the binary."),
122+
cl::NotHidden, cl::location(YkEmbedIR));
123+
}
124+
};
125+
} // namespace
126+
static ManagedStatic<cl::opt<bool, true>, CreateYkEmbedIRParser> YkEmbedIRParser;
127+
114128
void llvm::initYkOptions() {
115129
*YkAllocLLVMBCSectionParser;
116130
*YkAllocLLVMBBAddrMapSectionParser;
@@ -119,4 +133,5 @@ void llvm::initYkOptions() {
119133
*YkStackMapAdditionalLocsParser;
120134
*YkStackmapsSpillFixParser;
121135
*YkOptNoneAfterIRPassesParser;
136+
*YkEmbedIRParser;
122137
}

llvm/lib/YkIR/CMakeLists.txt

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
add_llvm_component_library(LLVMYkIR
2+
YkIRWriter.cpp
3+
4+
LINK_COMPONENTS
5+
Core
6+
MC
7+
Support
8+
)

llvm/lib/YkIR/YkIRWriter.cpp

+126
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
//===- YkIR/YkIRWRiter.cpp -- Yk JIT IR Serialiaser---------------------===//
2+
//
3+
// Converts an LLVM module into Yk's on-disk AOT IR.
4+
//
5+
//===-------------------------------------------------------------------===//
6+
7+
#include "llvm/ADT/Triple.h"
8+
#include "llvm/BinaryFormat/ELF.h"
9+
#include "llvm/IR/Constants.h"
10+
#include "llvm/IR/Module.h"
11+
#include "llvm/MC/MCContext.h"
12+
#include "llvm/MC/MCSectionELF.h"
13+
#include "llvm/MC/MCStreamer.h"
14+
15+
using namespace llvm;
16+
using namespace std;
17+
18+
namespace {
19+
20+
const char *SectionName = ".yk_ir";
21+
const uint32_t Magic = 0xedd5f00d;
22+
const uint32_t Version = 0;
23+
24+
enum OpCode {
25+
Nop = 0,
26+
};
27+
28+
class YkIRWriter {
29+
private:
30+
Module &M;
31+
MCStreamer &OutStreamer;
32+
33+
public:
34+
YkIRWriter(Module &M, MCStreamer &OutStreamer)
35+
: M(M), OutStreamer(OutStreamer) {}
36+
37+
// Serialises a null-terminated string.
38+
void serialiseString(StringRef S) {
39+
OutStreamer.emitBinaryData(S);
40+
OutStreamer.emitInt8(0); // null terminator.
41+
}
42+
43+
void serialiseBlock(BasicBlock &BB) {
44+
// num_instrs:
45+
OutStreamer.emitSizeT(BB.size());
46+
// instrs:
47+
for (Instruction &I : BB) {
48+
(void)I;
49+
OutStreamer.emitInt8(OpCode::Nop);
50+
}
51+
}
52+
53+
void serialiseFunc(Function &F) {
54+
// name:
55+
serialiseString(F.getName());
56+
// num_blocks:
57+
OutStreamer.emitSizeT(F.size());
58+
// blocks:
59+
for (BasicBlock &BB : F) {
60+
serialiseBlock(BB);
61+
}
62+
}
63+
64+
void serialise() {
65+
// header:
66+
OutStreamer.emitInt32(Magic);
67+
OutStreamer.emitInt32(Version);
68+
69+
// num_funcs:
70+
OutStreamer.emitSizeT(M.size());
71+
// funcs:
72+
for (Function &F : M) {
73+
serialiseFunc(F);
74+
}
75+
}
76+
};
77+
} // anonymous namespace
78+
79+
// Create an ELF section for storing Yk IR into.
80+
MCSection *createYkIRSection(MCContext &Ctx, const MCSection *TextSec) {
81+
if (Ctx.getObjectFileType() != MCContext::IsELF)
82+
return nullptr;
83+
84+
const MCSectionELF *ElfSec = static_cast<const MCSectionELF *>(TextSec);
85+
unsigned Flags = ELF::SHF_LINK_ORDER;
86+
StringRef GroupName;
87+
88+
// Ensure the loader loads it.
89+
Flags |= ELF::SHF_ALLOC;
90+
91+
return Ctx.getELFSection(SectionName, ELF::SHT_LLVM_BB_ADDR_MAP, Flags, 0,
92+
GroupName, true, ElfSec->getUniqueID(),
93+
cast<MCSymbolELF>(TextSec->getBeginSymbol()));
94+
}
95+
96+
// Emit a start/end IR marker.
97+
//
98+
// The JIT uses a start and end marker to make a Rust slice of the IR.
99+
void emitStartOrEndSymbol(MCContext &MCtxt, MCStreamer &OutStreamer,
100+
bool Start) {
101+
std::string SymName("ykllvm.yk_ir.");
102+
if (Start)
103+
SymName.append("start");
104+
else
105+
SymName.append("stop");
106+
107+
MCSymbol *Sym = MCtxt.getOrCreateSymbol(SymName);
108+
OutStreamer.emitSymbolAttribute(Sym, llvm::MCSA_Global);
109+
OutStreamer.emitLabel(Sym);
110+
}
111+
112+
namespace llvm {
113+
114+
// Emit Yk IR into the resulting ELF binary.
115+
void embedYkIR(MCContext &Ctx, MCStreamer &OutStreamer, Module &M) {
116+
MCSection *YkIRSec =
117+
createYkIRSection(Ctx, std::get<0>(OutStreamer.getCurrentSection()));
118+
119+
OutStreamer.pushSection();
120+
OutStreamer.switchSection(YkIRSec);
121+
emitStartOrEndSymbol(Ctx, OutStreamer, true);
122+
YkIRWriter(M, OutStreamer).serialise();
123+
emitStartOrEndSymbol(Ctx, OutStreamer, false);
124+
OutStreamer.popSection();
125+
}
126+
} // namespace llvm

yk_format_new_files.sh

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414
set -e
1515

16-
YK_DIRS="./clang/test/Yk ./llvm/lib/Transforms/Yk ./llvm/include/llvm/Transforms/Yk"
16+
YK_DIRS="./clang/test/Yk ./llvm/lib/Transforms/Yk ./llvm/include/llvm/Transforms/Yk llvm/lib/YkIR"
1717

1818
for dir in ${YK_DIRS}; do
1919
find ${dir} -type f -iname '*.cpp' -or -iname '*.h' -or -iname '*.c' | \

0 commit comments

Comments
 (0)