Created
December 20, 2018 15:16
-
-
Save KCreate/96a0d738967acf66ffc5a310e324fe5d to your computer and use it in GitHub Desktop.
IR Language Experiments
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Source code: | |
// | |
// int a = 25 | |
// int b = 20 | |
// int c = 0; | |
// | |
// if (a + b > 40) { | |
// c = 1; | |
// } else { | |
// c = 0; | |
// } | |
// | |
// return c | |
// | |
// | |
// IR with annotations: | |
// | |
// %0 = alloca | |
// %1 = alloca | |
// %2 = alloca | |
// store %0 25 | |
// store %1 25 | |
// store %2 0 | |
// %3 = add %0 %1 | |
// %4 = cmp sgt %3 40 | |
// br %4 .L0 .L1 | |
// .L0 | |
// store %2 1 | |
// br .L2 | |
// .L1 | |
// store %2 0 | |
// br .L2 | |
// .L2 | |
// %5 = load %2 | |
// ret %5 | |
// | |
class IRNode {}; | |
class IRBasicBlock extends IRNode { | |
constructor(id) { | |
super(); | |
this.id = id; | |
this.instructions = []; | |
} | |
}; | |
class IRLiteral extends IRNode { | |
constructor(value) { | |
super(); | |
this.value = value; | |
} | |
}; | |
class IRReference extends IRNode { | |
constructor(id) { | |
super(); | |
this.id = id; | |
} | |
}; | |
class IRLabel extends IRNode { | |
constructor(symbol) { | |
super(); | |
this.symbol = symbol; | |
} | |
}; | |
class IRAlloc extends IRNode {}; | |
class IRStore extends IRNode { | |
constructor(target, source) { | |
super(); | |
this.target = target; | |
this.source = source; | |
} | |
}; | |
class IRAdd extends IRNode { | |
constructor(left, right) { | |
super(); | |
this.left = left; | |
this.right = right; | |
} | |
}; | |
class IRCmp extends IRNode { | |
constructor(method, left, right) { | |
super(); | |
this.method = method; | |
this.left = left; | |
this.right = right; | |
} | |
}; | |
class IRBr extends IRNode { | |
constructor(condition, then_block, else_block) { | |
super(); | |
this.condition = condition; | |
this.then_block = then_block; | |
this.else_block = else_block; | |
} | |
}; | |
class IRJmp extends IRNode { | |
constructor(block) { | |
super(); | |
this.block = block; | |
} | |
}; | |
class IRLoad extends IRNode { | |
constructor(source) { | |
super(); | |
this.source = source; | |
} | |
}; | |
class IRRet extends IRNode { | |
constructor(source) { | |
super(); | |
this.source = source; | |
} | |
}; | |
class IRBuilder { | |
constructor() { | |
this.symbols = {}; | |
this.symbol_counter = 0; | |
this.blocks = {}; | |
this.current_block = undefined; | |
} | |
get_symbol() { | |
return new IRReference(this.symbol_counter++); | |
} | |
append_to_block(node) { | |
this.active_block().instructions.push(node); | |
} | |
append_to_block_with_symbol(node) { | |
this.append_to_block(node); | |
const symbol = this.get_symbol(); | |
this.assign_symbol(symbol, node); | |
return symbol; | |
} | |
create_new_block() { | |
const symbol = this.get_symbol(); | |
const block = new IRBasicBlock(symbol.id); | |
this.blocks[symbol.id] = block; | |
return new IRLabel(symbol); | |
} | |
set_current_block(symbol) { | |
this.current_block = symbol; | |
} | |
assign_symbol(symbol, node) { | |
this.symbols[symbol.id] = node; | |
} | |
lookup_symbol(symbol) { | |
return this.symbols[symbol.id]; | |
} | |
lookup_block(label) { | |
return this.blocks[label.symbol.id]; | |
} | |
active_block() { | |
return this.lookup_block(this.current_block); | |
} | |
}; | |
const builder = new IRBuilder(); | |
const mainBB = builder.create_new_block(); | |
builder.set_current_block(mainBB); | |
const sym_a = builder.append_to_block_with_symbol(new IRAlloc()); | |
const sym_b = builder.append_to_block_with_symbol(new IRAlloc()); | |
const sym_c = builder.append_to_block_with_symbol(new IRAlloc()); | |
builder.append_to_block(new IRStore(sym_a, new IRLiteral(25))); | |
builder.append_to_block(new IRStore(sym_b, new IRLiteral(20))); | |
builder.append_to_block(new IRStore(sym_c, new IRLiteral(0))); | |
const left_block = builder.create_new_block(); | |
const right_block = builder.create_new_block(); | |
const exit_block = builder.create_new_block(); | |
const sym_addition = builder.append_to_block_with_symbol(new IRAdd(sym_a, sym_b)); | |
const sym_comparison = builder.append_to_block_with_symbol(new IRCmp("sgt", sym_addition, new IRLiteral(40))); | |
builder.append_to_block(new IRBr(sym_comparison, left_block, right_block)); | |
builder.set_current_block(left_block); | |
builder.append_to_block(new IRStore(sym_c, new IRLiteral(1))); | |
builder.append_to_block(new IRJmp(exit_block)); | |
builder.set_current_block(right_block); | |
builder.append_to_block(new IRStore(sym_c, new IRLiteral(0))); | |
builder.append_to_block(new IRJmp(exit_block)); | |
builder.set_current_block(exit_block); | |
const value_c = builder.append_to_block_with_symbol(new IRLoad(sym_c)); | |
builder.append_to_block(new IRRet(value_c)); | |
console.dir(builder, { depth: null }); |
Author
KCreate
commented
Dec 20, 2018
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment