Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ COBJS := $(addprefix out/,$(notdir $(CSRCS:.c=.o)))
$(COBJS): out/%.o: ir/%.c
$(CC) -c -I. $(CFLAGS) $< -o $@

ELC_SRCS := elc.c util.c rb.c py.c js.c el.c vim.c tex.c cl.c sh.c sed.c java.c c.c x86.c i.c ws.c piet.c pietasm.c bef.c bf.c unl.c
ELC_SRCS := elc.c util.c rb.c py.c js.c el.c vim.c tex.c cl.c sh.c sed.c java.c c.c cpp.c x86.c i.c ws.c piet.c pietasm.c bef.c bf.c unl.c
ELC_SRCS := $(addprefix target/,$(ELC_SRCS))
COBJS := $(addprefix out/,$(notdir $(ELC_SRCS:.c=.o)))
$(COBJS): out/%.o: target/%.c
Expand Down Expand Up @@ -233,6 +233,11 @@ RUNNER := tools/runc.sh
include target.mk
$(OUT.eir.c.out): tools/runc.sh

TARGET := cpp
RUNNER := tools/runcpp.sh
include target.mk
$(OUT.eir.cpp.out): tools/runcpp.sh

ifeq ($(uname),Linux)
TARGET := x86
RUNNER :=
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ Currently, there are 18 backends:
* Vim script
* Bash
* C
* C++14 (compile-time)
* i386-linux
* C-INTERCAL
* Whitespace
Expand Down
173 changes: 173 additions & 0 deletions target/cpp.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
#include <ir/ir.h>
#include <target/util.h>

size_t BUF_SIZE = 10000;

static void cpp_defs(void) {
emit_line("#include <cstdio>");
emit_line("#include <utility>");
emit_line("");
emit_line("const size_t BUF_SIZE = %d;", BUF_SIZE);
emit_line("");
emit_line("constexpr char input[] =");
emit_line("#include \"input.txt\"");
emit_line(";");
emit_line("");
emit_line("struct buffer {");
emit_line(" unsigned int size;");
emit_line(" unsigned int b[BUF_SIZE];");
emit_line("};");
emit_line("template <size_t... I>");
emit_line("constexpr buffer make_buf_impl(unsigned int size, unsigned int* buf, std::index_sequence<I...>) {");
emit_line(" return buffer{size, {buf[I]...}};");
emit_line("}");
emit_line("constexpr buffer make_buf(unsigned int size, unsigned int* buf) {");
emit_line(" return make_buf_impl(size, buf, std::make_index_sequence<BUF_SIZE>{});");
emit_line("}");
}

static void cpp_init_state(Data* data) {
for (int i = 0; i < 7; i++) {
emit_line("unsigned int %s = 0;", reg_names[i]);
}

emit_line("unsigned int i_cur = 0;");
emit_line("unsigned int o_cur = 0;");
emit_line("unsigned int mem[1<<24] = {0};");
emit_line("unsigned int buf[BUF_SIZE] = {0};");

for (int mp = 0; data; data = data->next, mp++) {
if (data->v) {
emit_line("mem[%d] = %d;", mp, data->v);
}
}
}

static void cpp_emit_prologue(void) {
emit_line("");
emit_line("while (1) {");
inc_indent();
emit_line("switch (pc) {");
emit_line("case 0:");
inc_indent();
}

static void cpp_emit_epilogue(void) {
dec_indent();
emit_line("}");
emit_line("pc++;");
dec_indent();
emit_line("}");
emit_line("return make_buf(o_cur, buf);");
dec_indent();
emit_line("}");
}

static void cpp_emit_pc_change(int pc) {
emit_line("break;");
emit_line("");
dec_indent();
emit_line("case %d:", pc);
inc_indent();
}

static void cpp_emit_inst(Inst* inst) {
switch (inst->op) {
case MOV:
emit_line("%s = %s;", reg_names[inst->dst.reg], src_str(inst));
break;

case ADD:
emit_line("%s = (%s + %s) & " UINT_MAX_STR ";",
reg_names[inst->dst.reg],
reg_names[inst->dst.reg], src_str(inst));
break;

case SUB:
emit_line("%s = (%s - %s) & " UINT_MAX_STR ";",
reg_names[inst->dst.reg],
reg_names[inst->dst.reg], src_str(inst));
break;

case LOAD:
emit_line("%s = mem[%s];", reg_names[inst->dst.reg], src_str(inst));
break;

case STORE:
emit_line("mem[%s] = %s;", src_str(inst), reg_names[inst->dst.reg]);
break;

case PUTC:
emit_line("buf[o_cur++] = %s;", src_str(inst));
break;

case GETC:
emit_line("%s = (input[i_cur] ? input[i_cur++] : 0);",
reg_names[inst->dst.reg]);
break;

case EXIT:
emit_line("return make_buf(o_cur, buf);");
break;

case DUMP:
break;

case EQ:
case NE:
case LT:
case GT:
case LE:
case GE:
emit_line("%s = %s;",
reg_names[inst->dst.reg], cmp_str(inst, "1"));
break;

case JEQ:
case JNE:
case JLT:
case JGT:
case JLE:
case JGE:
case JMP:
emit_line("if (%s) pc = %s - 1;",
cmp_str(inst, "1"), value_str(&inst->jmp));
break;

default:
error("oops");
}
}

void cpp_emit_main_loop(Inst* inst) {
int prev_pc = 0;
for (; inst; inst = inst->next) {
if (prev_pc != inst->pc) {
cpp_emit_pc_change(inst->pc);
}
prev_pc = inst->pc;
cpp_emit_inst(inst);
}
}

void target_cpp(Module* module) {
cpp_defs();
emit_line("");
emit_line("constexpr buffer constexpr_main() {");
inc_indent();

cpp_init_state(module->data);
cpp_emit_prologue();
cpp_emit_main_loop(module->text);
cpp_emit_epilogue();

emit_line("");
emit_line("int main() {");
emit_line(" constexpr buffer buf = constexpr_main();");
emit_line(" constexpr unsigned int output_size = buf.size;");
emit_line("");
emit_line(" for(int i = 0; i < output_size; ++i) {");
emit_line(" putchar(buf.b[i]);");
emit_line(" }");
emit_line("}");
}
3 changes: 3 additions & 0 deletions target/elc.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ void target_sh(Module* module);
void target_sed(Module* module);
void target_java(Module* module);
void target_c(Module* module);
void target_cpp(Module* module);
void target_x86(Module* module);
void target_i(Module* module);
void target_ws(Module* module);
Expand Down Expand Up @@ -49,6 +50,8 @@ static target_func_t get_target_func(const char* ext) {
return target_java;
} else if (!strcmp(ext, "c")) {
return target_c;
} else if (!strcmp(ext, "cpp")) {
return target_cpp;
} else if (!strcmp(ext, "x86")) {
return target_x86;
} else if (!strcmp(ext, "i")) {
Expand Down
21 changes: 21 additions & 0 deletions tools/runcpp.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#!/bin/bash

set -e

dir=$(mktemp -d)
mkdir -p $dir
cp $1 $dir
infile=${dir}/input.txt

cat > $infile

if [ ! -s $infile ]; then
echo '""' > $infile
else
sed -i '1s/^/R"(/' $infile
echo ')"' >> $infile
fi

g++-6 ${dir}/$(basename $1) -o $1.exe
rm -fr $dir
./$1.exe