Skip to content

Commit d7d9f83

Browse files
committed
add some more bcs
1 parent 62720df commit d7d9f83

File tree

2 files changed

+252
-17
lines changed

2 files changed

+252
-17
lines changed

rir/src/compiler/gnur2pir/gnur2pir.cpp

Lines changed: 248 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "simple_instruction_list.h"
1919
#include "utils/FormalArgs.h"
2020

21+
#include <initializer_list>
2122
#include <sstream>
2223
#include <unordered_map>
2324
#include <vector>
@@ -333,6 +334,10 @@ class RBCCode {
333334
bool operator==(const Iterator& other) const {
334335
return pos == other.pos;
335336
}
337+
size_t operator-(const Iterator& other) const {
338+
assert(pos >= other.pos);
339+
return pos - other.pos;
340+
}
336341

337342
size_t label(const Iterator& begin) const {
338343
return pos - begin.pos + 1;
@@ -370,26 +375,67 @@ class RBCCode {
370375

371376
struct Stack {
372377
private:
373-
std::stack<Value*> stack;
378+
std::vector<Value*> stack;
374379

375380
public:
376-
void push(Value* v) { stack.push(v); }
381+
void push(Value* v) { stack.push_back(v); }
377382
Value* pop() {
378-
auto v = stack.top();
379-
stack.pop();
383+
auto v = stack.back();
384+
stack.pop_back();
380385
return v;
381386
}
382-
~Stack() { assert(stack.empty()); }
387+
bool isEmpty() const { return stack.empty(); }
388+
friend struct CompilerInfo;
383389
};
384390

385391
struct CompilerInfo {
386392
CompilerInfo(SEXP src, Stack& stack, Builder& insert)
387-
: src(src), stack(stack), insert(insert) {}
393+
: src(src), stack(stack), insert(insert) {
394+
basicBlocks[1] = insert.getCurrentBB();
395+
}
396+
BB* getBB(size_t pos) {
397+
auto f = basicBlocks.find(pos);
398+
if (f != basicBlocks.end())
399+
return f->second;
400+
return basicBlocks
401+
.emplace(pos, new BB(insert.code, insert.code->nextBBId++))
402+
.first->second;
403+
}
388404
SEXP src;
389405
Stack& stack;
390406
Builder& insert;
391407
std::unordered_set<size_t> mergepoints;
408+
std::unordered_map<BB*, Stack> bbState;
409+
std::unordered_map<size_t, BB*> basicBlocks;
392410
std::unordered_map<size_t, size_t> jumps;
411+
412+
void merge(std::initializer_list<size_t> trgs) {
413+
for (auto trg : trgs) {
414+
auto bb = getBB(trg);
415+
if (!mergepoints.count(trg)) {
416+
assert(!bbState.count(bb));
417+
bbState[bb] = stack;
418+
continue;
419+
}
420+
421+
auto state = bbState.find(bb);
422+
if (state == bbState.end()) {
423+
Stack trgStack;
424+
for (auto v : stack.stack) {
425+
trgStack.push(*bb->insert(
426+
bb->end(), new Phi({{insert.getCurrentBB(), v}})));
427+
}
428+
bbState.emplace(bb, trgStack);
429+
} else {
430+
Stack& trgStack = state->second;
431+
for (size_t pos = 0; pos < trgStack.stack.size(); ++pos) {
432+
Phi::Cast(trgStack.stack[pos])
433+
->addInput(insert.getCurrentBB(), stack.stack[pos]);
434+
}
435+
}
436+
}
437+
stack.stack.clear();
438+
}
393439
};
394440

395441
static void findMerges(const RBCCode& bytecode, CompilerInfo& info) {
@@ -430,6 +476,7 @@ struct BCCompiler {
430476

431477
void push(Value* v) { cmp.stack.push(v); }
432478

479+
bool stackEmpty() { return cmp.stack.isEmpty(); }
433480
Value* pop() { return cmp.stack.pop(); }
434481

435482
Instruction* insertPush(Instruction* i) {
@@ -447,34 +494,74 @@ struct BCCompiler {
447494
Value* env() { return cmp.insert.env; }
448495

449496
template <RBC::Id BC>
450-
void compile(const RBC&);
497+
void compile(const RBC&, size_t pos);
451498
};
452499

453500
// Start instructions translation
454501

455502
template <>
456-
void BCCompiler::compile<RBC::GETVAR_OP>(const RBC& bc) {
503+
void BCCompiler::compile<RBC::GETVAR_OP>(const RBC& bc, size_t pos) {
457504
auto v = insert(new LdVar(cnst(bc.imm(0)), env()));
458505
insertPush(new Force(v, env(), Tombstone::framestate()));
459506
}
460507

461508
template <>
462-
void BCCompiler::compile<RBC::RETURN_OP>(const RBC& bc) {
509+
void BCCompiler::compile<RBC::RETURN_OP>(const RBC& bc, size_t pos) {
463510
insert(new Return(pop()));
464511
}
465512

466513
template <>
467-
void BCCompiler::compile<RBC::LDCONST_OP>(const RBC& bc) {
514+
void BCCompiler::compile<RBC::LDCONST_OP>(const RBC& bc, size_t pos) {
468515
push(insert(new LdConst(cnst(bc.imm(0)))));
469516
}
470517

471518
template <>
472-
void BCCompiler::compile<RBC::ADD_OP>(const RBC& bc) {
519+
void BCCompiler::compile<RBC::ADD_OP>(const RBC& bc, size_t pos) {
473520
auto a = pop();
474521
auto b = pop();
475522
insertPush(new Add(a, b, env(), bc.imm(0)));
476523
}
477524

525+
template <>
526+
void BCCompiler::compile<RBC::BRIFNOT_OP>(const RBC& bc, size_t pos) {
527+
auto t = insert(new CheckTrueFalse(pop()));
528+
auto label = bc.imm(1);
529+
insert(new Branch(t));
530+
auto fallPos = pos + bc.imm() + 1;
531+
auto fall = cmp.getBB(fallPos);
532+
auto trg = cmp.getBB(label);
533+
cmp.insert.setBranch(fall, trg);
534+
cmp.merge({fallPos, (size_t)label});
535+
}
536+
537+
template <>
538+
void BCCompiler::compile<RBC::GOTO_OP>(const RBC& bc, size_t pos) {
539+
auto label = bc.imm(0);
540+
auto trg = cmp.getBB(label);
541+
cmp.insert.setNext(trg);
542+
cmp.merge({(size_t)label});
543+
}
544+
545+
template <>
546+
void BCCompiler::compile<RBC::LDNULL_OP>(const RBC& bc, size_t pos) {
547+
push(Nil::instance());
548+
}
549+
550+
template <>
551+
void BCCompiler::compile<RBC::INVISIBLE_OP>(const RBC& bc, size_t pos) {
552+
insert(new Invisible());
553+
}
554+
555+
template <>
556+
void BCCompiler::compile<RBC::INCLNK_OP>(const RBC& bc, size_t pos) {
557+
insert(new Invisible());
558+
}
559+
560+
template <>
561+
void BCCompiler::compile<RBC::DECLNK_OP>(const RBC& bc, size_t pos) {
562+
insert(new Invisible());
563+
}
564+
478565
// End instructions translation
479566

480567
pir::ClosureVersion* Gnur2Pir::compile(SEXP src, const std::string& name) {
@@ -502,25 +589,169 @@ pir::ClosureVersion* Gnur2Pir::compile(SEXP src, const std::string& name) {
502589
BCCompiler bccompiler(info);
503590

504591
#define SUPPORTED_INSTRUCTIONS(V) \
592+
V(RBC::GOTO_OP) \
505593
V(RBC::GETVAR_OP) \
506594
V(RBC::RETURN_OP) \
507595
V(RBC::LDCONST_OP) \
508-
V(RBC::ADD_OP)
596+
V(RBC::ADD_OP) \
597+
V(RBC::LDNULL_OP) \
598+
V(RBC::INVISIBLE_OP) \
599+
V(RBC::INCLNK_OP) \
600+
V(RBC::DECLNK_OP) \
601+
V(RBC::BRIFNOT_OP)
602+
603+
#define UNSUPPORTED_INSTRUCTIONS(V) \
604+
V(RBC::BCMISMATCH_OP) \
605+
V(RBC::POP_OP) \
606+
V(RBC::DUP_OP) \
607+
V(RBC::PRINTVALUE_OP) \
608+
V(RBC::STARTLOOPCNTXT_OP) \
609+
V(RBC::ENDLOOPCNTXT_OP) \
610+
V(RBC::DOLOOPNEXT_OP) \
611+
V(RBC::DOLOOPBREAK_OP) \
612+
V(RBC::STARTFOR_OP) \
613+
V(RBC::STEPFOR_OP) \
614+
V(RBC::ENDFOR_OP) \
615+
V(RBC::SETLOOPVAL_OP) \
616+
V(RBC::LDTRUE_OP) \
617+
V(RBC::LDFALSE_OP) \
618+
V(RBC::DDVAL_OP) \
619+
V(RBC::SETVAR_OP) \
620+
V(RBC::GETFUN_OP) \
621+
V(RBC::GETGLOBFUN_OP) \
622+
V(RBC::GETSYMFUN_OP) \
623+
V(RBC::GETBUILTIN_OP) \
624+
V(RBC::GETINTLBUILTIN_OP) \
625+
V(RBC::CHECKFUN_OP) \
626+
V(RBC::MAKEPROM_OP) \
627+
V(RBC::DOMISSING_OP) \
628+
V(RBC::SETTAG_OP) \
629+
V(RBC::DODOTS_OP) \
630+
V(RBC::PUSHARG_OP) \
631+
V(RBC::PUSHCONSTARG_OP) \
632+
V(RBC::PUSHNULLARG_OP) \
633+
V(RBC::PUSHTRUEARG_OP) \
634+
V(RBC::PUSHFALSEARG_OP) \
635+
V(RBC::CALL_OP) \
636+
V(RBC::CALLBUILTIN_OP) \
637+
V(RBC::CALLSPECIAL_OP) \
638+
V(RBC::MAKECLOSURE_OP) \
639+
V(RBC::UMINUS_OP) \
640+
V(RBC::UPLUS_OP) \
641+
V(RBC::SUB_OP) \
642+
V(RBC::MUL_OP) \
643+
V(RBC::DIV_OP) \
644+
V(RBC::EXPT_OP) \
645+
V(RBC::SQRT_OP) \
646+
V(RBC::EXP_OP) \
647+
V(RBC::EQ_OP) \
648+
V(RBC::NE_OP) \
649+
V(RBC::LT_OP) \
650+
V(RBC::LE_OP) \
651+
V(RBC::GE_OP) \
652+
V(RBC::GT_OP) \
653+
V(RBC::AND_OP) \
654+
V(RBC::OR_OP) \
655+
V(RBC::NOT_OP) \
656+
V(RBC::DOTSERR_OP) \
657+
V(RBC::STARTASSIGN_OP) \
658+
V(RBC::ENDASSIGN_OP) \
659+
V(RBC::STARTSUBSET_OP) \
660+
V(RBC::DFLTSUBSET_OP) \
661+
V(RBC::STARTSUBASSIGN_OP) \
662+
V(RBC::DFLTSUBASSIGN_OP) \
663+
V(RBC::STARTC_OP) \
664+
V(RBC::DFLTC_OP) \
665+
V(RBC::STARTSUBSET2_OP) \
666+
V(RBC::DFLTSUBSET2_OP) \
667+
V(RBC::STARTSUBASSIGN2_OP) \
668+
V(RBC::DFLTSUBASSIGN2_OP) \
669+
V(RBC::DOLLAR_OP) \
670+
V(RBC::DOLLARGETS_OP) \
671+
V(RBC::ISNULL_OP) \
672+
V(RBC::ISLOGICAL_OP) \
673+
V(RBC::ISINTEGER_OP) \
674+
V(RBC::ISDOUBLE_OP) \
675+
V(RBC::ISCOMPLEX_OP) \
676+
V(RBC::ISCHARACTER_OP) \
677+
V(RBC::ISSYMBOL_OP) \
678+
V(RBC::ISOBJECT_OP) \
679+
V(RBC::ISNUMERIC_OP) \
680+
V(RBC::VECSUBSET_OP) \
681+
V(RBC::MATSUBSET_OP) \
682+
V(RBC::VECSUBASSIGN_OP) \
683+
V(RBC::MATSUBASSIGN_OP) \
684+
V(RBC::AND1ST_OP) \
685+
V(RBC::AND2ND_OP) \
686+
V(RBC::OR1ST_OP) \
687+
V(RBC::OR2ND_OP) \
688+
V(RBC::GETVAR_MISSOK_OP) \
689+
V(RBC::DDVAL_MISSOK_OP) \
690+
V(RBC::VISIBLE_OP) \
691+
V(RBC::SETVAR2_OP) \
692+
V(RBC::STARTASSIGN2_OP) \
693+
V(RBC::ENDASSIGN2_OP) \
694+
V(RBC::SETTER_CALL_OP) \
695+
V(RBC::GETTER_CALL_OP) \
696+
V(RBC::SWAP_OP) \
697+
V(RBC::DUP2ND_OP) \
698+
V(RBC::SWITCH_OP) \
699+
V(RBC::RETURNJMP_OP) \
700+
V(RBC::STARTSUBSET_N_OP) \
701+
V(RBC::STARTSUBASSIGN_N_OP) \
702+
V(RBC::VECSUBSET2_OP) \
703+
V(RBC::MATSUBSET2_OP) \
704+
V(RBC::VECSUBASSIGN2_OP) \
705+
V(RBC::MATSUBASSIGN2_OP) \
706+
V(RBC::STARTSUBSET2_N_OP) \
707+
V(RBC::STARTSUBASSIGN2_N_OP) \
708+
V(RBC::SUBSET_N_OP) \
709+
V(RBC::SUBSET2_N_OP) \
710+
V(RBC::SUBASSIGN_N_OP) \
711+
V(RBC::SUBASSIGN2_N_OP) \
712+
V(RBC::LOG_OP) \
713+
V(RBC::LOGBASE_OP) \
714+
V(RBC::MATH1_OP) \
715+
V(RBC::DOTCALL_OP) \
716+
V(RBC::COLON_OP) \
717+
V(RBC::SEQALONG_OP) \
718+
V(RBC::SEQLEN_OP) \
719+
V(RBC::BASEGUARD_OP) \
720+
V(RBC::DECLNK_N_OP)
509721

510722
for (auto pc = bytecode.begin(); pc != bytecode.end(); ++pc) {
511723
auto bc = *pc;
724+
auto pos = (pc - bytecode.begin()) + 1;
725+
auto hasBB = info.basicBlocks.find(pos);
726+
if (hasBB != info.basicBlocks.end()) {
727+
info.insert.reenterBB(hasBB->second);
728+
auto state = info.bbState.find(hasBB->second);
729+
if (state != info.bbState.end())
730+
info.stack = state->second;
731+
}
732+
512733
switch (bc.id) {
513734
#define V(BC) \
514735
case BC: \
515-
bccompiler.compile<BC>(bc); \
736+
bccompiler.compile<BC>(bc, pos); \
516737
break;
517738
SUPPORTED_INSTRUCTIONS(V)
518739
#undef V
519740

520-
default:
521-
std::cerr << "Could not compile " << *pc << "\n";
522-
assert(false);
523-
return nullptr;
741+
#define V(BC) \
742+
case BC: \
743+
std::cerr << "Could not compile " << *pc << "\n"; \
744+
assert(false); \
745+
return nullptr;
746+
UNSUPPORTED_INSTRUCTIONS(V)
747+
#undef V
748+
}
749+
750+
auto next = pos + 1 + bc.imm();
751+
if (bc.falls() && info.mergepoints.count(next) &&
752+
!info.stack.isEmpty()) {
753+
info.merge({next});
754+
info.insert.getCurrentBB()->setNext(info.getBB(next));
524755
}
525756
}
526757
return v;

rir/tests/gnur2pir.R

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,7 @@ test <- function(f, arg, expected) {
88
test(function(a) 1,, 1)
99
test(function(a) a, 1, 1)
1010
test(function(a) a+1, 1, 2)
11+
test(function(a) if (a) 1, TRUE, 1)
12+
test(function(a) if (a) 1, FALSE, NULL)
13+
test(function(a) 1 + if (a) 1, T, 2)
14+
test(function(a) 2 - 1 + if (a) 1, T, 2)

0 commit comments

Comments
 (0)