Skip to content

Instantly share code, notes, and snippets.

View mshockwave's full-sized avatar

Min-Yih Hsu mshockwave

View GitHub Profile
@mshockwave
mshockwave / varlen-code-emitter.md
Last active December 6, 2021 03:25
A new CodeEmitterGen infrastructure for variable-length instructions

A new CodeEmitterGen infrastructure for variable-length instructions

Background

CodeEmitterGen is a TableGen backend that generates instruction encoder functions for MCCodeEmitter from a concise TableGen syntax. It is, however, almost exclusively designed for targets that use fixed-length instructions. It's nearly impossible to use this infrastructure to describe instruction encoding scheme for ISAs with variable-length instructions, like X86 and M68k.

To have a better understanding on this problem, let's look at an example. For a fixed-length instruction ISA, developers write the following TableGen syntax to describe an instruction encoding:

class MyInst<(outs GR64:$dst), (ins GR64, i16imm:$imm)> : Instruction {
    bits<32> Inst;

 bits&lt;4&gt; dst;
@mshockwave
mshockwave / code-emitter-roadmap.md
Last active November 10, 2021 21:33
New M68k Instruction Encoding Plan

New M68k Instruction Encoding Plan

Or "how to replace the exotic code-beads-based encoder"

Background

The M68k LLVM backend has been using an unique approach called code beads to encode instructions. This scheme has its own TableGen backend as well as a non-trivial (TableGen code) infrastructure to support TableGen-ed instruction declarations. This brings lots of burdens on the maintainence side since it completely deviates from the normal instruction encoding scheme used by majority of the backends.

Not to mention that the chances for future targets / backends to find code beads TableGen backend useful is pretty low, due to the fact that the entire code beads framework was almost exclusively designed for ISA that has variable-length instruction encoding -- a thing that is not widely adopted by modern processors anymore.

The last straw that broke the camel's back is probably the fact that sometimes, even I had a hard time to comprehend a piece of code beads TableGen snippet right away. Don't

// Doesn't work on windows. The C++ code doesn't catch C++ exceptions if they've
// traversed a Pony frame. This is suspected to be related to how SEH and LLVM
// exception code generation interact.
// See https://github.com/ponylang/ponyc/issues/2455 for more details.
//
// This test is disabled on LLVM 3.9 and 4.0 because exceptions crossing JIT
// boundaries are broken with the ORC JIT on these versions.
#if !defined(PLATFORM_IS_WINDOWS) && (PONY_LLVM >= 500)
TEST_F(CodegenTest, TryBlockCantCatchCppExcept)
{
if(!CodeGenOpts.ExtraProteinAmount.empty()) {
MPM.add(createExtraProteinLegacyPass(CodeGenOpts.ExtraProteinAmount.Duplicate,
CodeGenOpts.ExtraProteinAmount.Amend));
}
if(!CodeGenOpts.ExtraProteinAmount.empty()) {
// We need mem2reg and sroa for better code shape
// these two would be added by default when OptLevel >= 1
// so make sure they're added even when OptLevel == 0
if(PMBuilder.OptLevel < 1) {
FPM.add(createSROAPass());
MPM.add(createPromoteMemoryToRegisterPass());
}
MPM.add(createExtraProteinLegacyPass(CodeGenOpts.ExtraProteinAmount.Duplicate,
CodeGenOpts.ExtraProteinAmount.Amend));
for(const auto& Arg : Args.getAllArgValues(OPT_extra_protein_amount)) {
StringRef Val(Arg);
if(Val.endswith("x")) {
// Duplicate
uint32_t Num = 0;
Val.consumeInteger(10, Num);
Opts.ExtraProteinAmount.Duplicate += Num;
} else {
// Amend
uint32_t Num = 0;
if(const Arg *A = Args.getLastArg(options::OPT_extra_protein_EQ)) {
StringRef Val = A->getValue();
uint32_t NumAmount = 0;
Val.consumeInteger(10, NumAmount);
if(Val == "lb") {
// Turn 'pound' to 'gram'
NumAmount *= 454; // 1 pound == 453.59 gram
Val = "g";
}
def extra_protein_EQ : Joined<["-", "--"], "add-extra-protein=">, Flags<[DriverOption]>,
HelpText<"Add extra protein for all loops.">;
def extra_protein : Flag<["-", "--"], "add-extra-protein">, Flags<[DriverOption]>,
Alias<extra_protein_EQ>, AliasArgs<["2x"]>,
HelpText<"Add 2x extra protein for all loops.">;
@mshockwave
mshockwave / friend_of_friend.cc
Created August 29, 2018 01:55
C++: Friend of my friend is not my friend!
#include <iostream>
class C {
friend class A;
int Private;
};
class A {
//friend class B;
int Private;
void PassManagerBuilder::populateFunctionPassManager(
legacy::FunctionPassManager &FPM) {
//...Some code skipped...
if (OptLevel == 0) return;
addInitialAliasAnalysisPasses(FPM);
FPM.add(createCFGSimplificationPass());
FPM.add(createSROAPass());