Skip to content

Instantly share code, notes, and snippets.

@keiichiw
Last active February 26, 2017 03:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save keiichiw/d895ee5b10eb2ae1db150856f73cd1b9 to your computer and use it in GitHub Desktop.
Save keiichiw/d895ee5b10eb2ae1db150856f73cd1b9 to your computer and use it in GitHub Desktop.
ELVMの変換例: EIR, C++Template, C, constexprの比較
# 出典: https://github.com/shinh/elvm/blob/master/test/06mem.eir
# "MEM" と出力される
mov B, 77
store B, 300
load A, 300
load A, 300
putc A
mov B, 69
store B, 30
store B, 30
load A, 30
putc A
add A, 8
putc A
load A, 556
add A, 10
putc A
exit
// Template Meta Programming バックエンドの出力
#include <cstdio>
#include "cpp_template_lib.hpp" // https://gist.github.com/kw-udon/6248197ec8fdc681b63e4cb8271fac56
typedef enum { a, b, c, d, bp, sp } Reg_Name;
template <typename r0, typename m0, typename b0, int pc>
struct func_switch_impl { typedef inc_pc<r0, m0, b0> result; };
template <typename r0, typename m0, typename b0>
struct func_switch_impl<r0, m0, b0, 0> {
typedef jmp_imm<r0, 1> r1;
typedef inc_pc<r1, m0, b0> result;
};
template <typename r0, typename m0, typename b0>
struct func_switch_impl<r0, m0, b0, 1> {
typedef mov_imm<r0, b, 77> r1;
typedef store_imm<r1, m0, b, 300> m1;
typedef load_imm<r1, m1, a, 300> r2;
typedef load_imm<r2, m1, a, 300> r3;
typedef putc_reg<r3, b0,a> b1;
typedef mov_imm<r3, b, 69> r4;
typedef store_imm<r4, m1, b, 30> m2;
typedef store_imm<r4, m2, b, 30> m3;
typedef load_imm<r4, m3, a, 30> r5;
typedef putc_reg<r5, b1,a> b2;
typedef add_imm<r5, a, 8> r6;
typedef putc_reg<r6, b2,a> b3;
typedef load_imm<r6, m3, a, 556> r7;
typedef add_imm<r7, a, 10> r8;
typedef putc_reg<r8, b3,a> b4;
typedef exit_inst<r8> r9;
typedef inc_pc<r9, m3, b4> result;
};
template <typename env, int pc>
struct func_switch : func_switch_impl<typename env::regs, typename env::mem, typename env::buf, pc>::result {};
template <typename env, bool, int>
struct main_loop { typedef env result; };
template <typename env, int pc>
struct main_loop<env, false, pc> {
typedef func_switch<env, pc> env2;
typedef typename main_loop<env2, env2::regs::exit_flag, env2::regs::pc>::result result;
};
struct calc_main {
typedef init_memory<MEM_SIZE> mem0;
typedef store_value<mem0, 0, 1> mem1;
typedef init_regs<0> regs;
typedef make_env<regs, mem1, Nil> env;
typedef main_loop<env, false, 0>::result result;
};
int main() {
typedef calc_main::result result;
print_buffer<result::buf>::run();
}
// 参考のため、Cバックエンドの出力
#include <stdio.h>
#include <stdlib.h>
unsigned int a;
unsigned int b;
unsigned int c;
unsigned int d;
unsigned int bp;
unsigned int sp;
unsigned int pc;
unsigned int mem[1<<24];
void func0() {
while (0 <= pc && pc < 512) {
switch (pc) {
case -1: /* dummy */
break;
case 0:
if (1) pc = 1 - 1;
break;
case 1:
b = 77;
mem[300] = b;
a = mem[300];
a = mem[300];
putchar(a);
b = 69;
mem[30] = b;
mem[30] = b;
a = mem[30];
putchar(a);
a = (a + 8) & 16777215;
putchar(a);
a = mem[556];
a = (a + 10) & 16777215;
putchar(a);
exit(0);
}
pc++;
}
}
int main() {
mem[0] = 1;
while (1) {
switch (pc / 512 | 0) {
case 0:
func0();
break;
}
}
return 1;
}
// 参考のため、constexprバックエンドの出力
#include <cstdio>
#include <utility>
const size_t BUF_SIZE = 10000;
constexpr char input[] =
#include "input.txt"
;
struct buffer {
unsigned int size;
unsigned int b[BUF_SIZE];
};
template <size_t... I>
constexpr buffer make_buf_impl(unsigned int size, unsigned int* buf, std::index_sequence<I...>) {
return buffer{size, {buf[I]...}};
}
constexpr buffer make_buf(unsigned int size, unsigned int* buf) {
return make_buf_impl(size, buf, std::make_index_sequence<BUF_SIZE>{});
}
constexpr buffer constexpr_main() {
unsigned int a = 0;
unsigned int b = 0;
unsigned int c = 0;
unsigned int d = 0;
unsigned int bp = 0;
unsigned int sp = 0;
unsigned int pc = 0;
unsigned int i_cur = 0;
unsigned int o_cur = 0;
unsigned int mem[1<<24] = {0};
unsigned int buf[BUF_SIZE] = {0};
mem[0] = 1;
while (1) {
switch (pc) {
case 0:
if (1) pc = 1 - 1;
break;
case 1:
b = 77;
mem[300] = b;
a = mem[300];
a = mem[300];
buf[o_cur++] = a;
b = 69;
mem[30] = b;
mem[30] = b;
a = mem[30];
buf[o_cur++] = a;
a = (a + 8) & 16777215;
buf[o_cur++] = a;
a = mem[556];
a = (a + 10) & 16777215;
buf[o_cur++] = a;
return make_buf(o_cur, buf);
}
pc++;
}
return make_buf(o_cur, buf);
}
int main() {
constexpr buffer buf = constexpr_main();
constexpr unsigned int output_size = buf.size;
for(int i = 0; i < output_size; ++i) {
putchar(buf.b[i]);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment