diff --git a/benchmarks/core/rot13.bril b/benchmarks/core/rot13.bril new file mode 100644 index 000000000..ee1dc3cf0 --- /dev/null +++ b/benchmarks/core/rot13.bril @@ -0,0 +1,17 @@ +# ARGS: 10 +# Compute the char shifted forward by 13 (0-indexed) +@main(input: int) { + aed: int = call @rot input; + print aed; +} +@rot(n: int):int{ + thirteen: int = const 13; + twenty_six: int = const 26; + shifted: int = add n thirteen; + over: bool = ge shifted twenty_six; + br over .if .else; +.if: + shifted: int = sub shifted twenty_six; +.else: + ret shifted; +} diff --git a/benchmarks/core/rot13.out b/benchmarks/core/rot13.out new file mode 100644 index 000000000..409940768 --- /dev/null +++ b/benchmarks/core/rot13.out @@ -0,0 +1 @@ +23 diff --git a/benchmarks/core/rot13.prof b/benchmarks/core/rot13.prof new file mode 100644 index 000000000..c1c0cab70 --- /dev/null +++ b/benchmarks/core/rot13.prof @@ -0,0 +1 @@ +total_dyn_inst: 8 diff --git a/cs6120/lesson_2/ackermann.json b/cs6120/lesson_2/ackermann.json new file mode 100644 index 000000000..40a981a50 --- /dev/null +++ b/cs6120/lesson_2/ackermann.json @@ -0,0 +1,205 @@ +{ + "functions": [ + { + "args": [ + { + "name": "m", + "type": "int" + }, + { + "name": "n", + "type": "int" + } + ], + "instrs": [ + { + "dest": "zero", + "op": "const", + "type": "int", + "value": 0 + }, + { + "dest": "one", + "op": "const", + "type": "int", + "value": 1 + }, + { + "args": [ + "m", + "zero" + ], + "dest": "cond_m", + "op": "eq", + "type": "bool" + }, + { + "args": [ + "cond_m" + ], + "labels": [ + "m_zero", + "m_nonzero" + ], + "op": "br" + }, + { + "label": "m_zero" + }, + { + "args": [ + "n", + "one" + ], + "dest": "tmp", + "op": "add", + "type": "int" + }, + { + "args": [ + "tmp" + ], + "op": "ret" + }, + { + "label": "m_nonzero" + }, + { + "args": [ + "n", + "zero" + ], + "dest": "cond_n", + "op": "eq", + "type": "bool" + }, + { + "args": [ + "cond_n" + ], + "labels": [ + "n_zero", + "n_nonzero" + ], + "op": "br" + }, + { + "label": "n_zero" + }, + { + "args": [ + "m", + "one" + ], + "dest": "m1", + "op": "sub", + "type": "int" + }, + { + "args": [ + "m1", + "one" + ], + "dest": "tmp", + "funcs": [ + "ack" + ], + "op": "call", + "type": "int" + }, + { + "args": [ + "tmp" + ], + "op": "ret" + }, + { + "label": "n_nonzero" + }, + { + "args": [ + "m", + "one" + ], + "dest": "m1", + "op": "sub", + "type": "int" + }, + { + "args": [ + "n", + "one" + ], + "dest": "n1", + "op": "sub", + "type": "int" + }, + { + "args": [ + "m", + "n1" + ], + "dest": "t1", + "funcs": [ + "ack" + ], + "op": "call", + "type": "int" + }, + { + "args": [ + "m1", + "t1" + ], + "dest": "t2", + "funcs": [ + "ack" + ], + "op": "call", + "type": "int" + }, + { + "args": [ + "t2" + ], + "op": "ret" + } + ], + "name": "ack", + "type": "int" + }, + { + "args": [ + { + "name": "m", + "type": "int" + }, + { + "name": "n", + "type": "int" + } + ], + "instrs": [ + { + "args": [ + "m", + "n" + ], + "dest": "tmp", + "funcs": [ + "ack" + ], + "op": "call", + "type": "int" + }, + { + "args": [ + "tmp" + ], + "op": "print" + } + ], + "name": "main" + } + ] +} \ No newline at end of file diff --git a/cs6120/lesson_2/ackermann.out b/cs6120/lesson_2/ackermann.out new file mode 100644 index 000000000..015008f40 --- /dev/null +++ b/cs6120/lesson_2/ackermann.out @@ -0,0 +1,2 @@ +ack +main diff --git a/cs6120/lesson_2/blocks.py b/cs6120/lesson_2/blocks.py new file mode 100644 index 000000000..effb7c833 --- /dev/null +++ b/cs6120/lesson_2/blocks.py @@ -0,0 +1,35 @@ +import json +import sys + +terminators = ('br', 'jmp', 'ret') + +def blocks(filename): + with open(filename) as file: + program = json.load(file) + function = program["functions"][0]["instrs"] + cur_block = (None, []) + all_blocks = [cur_block] + for instr in function: + if "op" in instr: + cur_block[1].append(instr) + if(instr["op"] in terminators): + cur_block = (None, []) + all_blocks.append(cur_block) + else: + # blocks that are empty and have no labels can safely be removed + if(len(cur_block[1]) == 0 and cur_block[0] == None): + all_blocks = all_blocks[:-1] + cur_block = (instr["label"], []) + all_blocks.append(cur_block) + # remove empty last block + if(len(cur_block[1]) == 0 and cur_block[0] == None): + all_blocks = all_blocks[:-1] + return all_blocks + + +if __name__ == "__main__": + filename = sys.argv[1] + all_blocks = blocks(filename) + for (label, contents) in all_blocks: + print(label) + print(contents) \ No newline at end of file diff --git a/cs6120/lesson_2/branch_names.py b/cs6120/lesson_2/branch_names.py new file mode 100644 index 000000000..4d603feed --- /dev/null +++ b/cs6120/lesson_2/branch_names.py @@ -0,0 +1,9 @@ +import json +import sys + +if __name__ == "__main__": + filename = sys.argv[1] + with open(filename) as file: + program = json.load(file) + for function in program["functions"]: + print(function["name"]) \ No newline at end of file diff --git a/cs6120/lesson_2/cfg.py b/cs6120/lesson_2/cfg.py new file mode 100644 index 000000000..872d6a0d0 --- /dev/null +++ b/cs6120/lesson_2/cfg.py @@ -0,0 +1,61 @@ +import sys +import blocks + +def change_labels(all_blocks): + new_name = "label " + new_num = 0 + all_labels = [block[0] for block in all_blocks] + for i in range(len(all_labels)): + if(all_labels[i] == None): + while((new_name + str(new_num)) in all_labels): + new_num += 1 + all_labels[i] = new_name + str(new_num) + + for i in range(len(all_blocks)): + all_blocks[i] = (all_labels[i], all_blocks[i][1]) + return all_blocks + +def build_cfg(all_blocks): + successors = {"entry": [], "exit": []} + for block in all_blocks: + successors[block[0]] = [] + # dummy entry block + successors["entry"] = [all_blocks[0][0]] + + for i in range(len(all_blocks)): + # last entry is ret -> successor = exit + # last entry is br -> successors = br targets + # last entry is jmp -> successor = jmp + # last entry is nothing -> successor = next block (or exit if last block) + last_entry = all_blocks[i][1][-1] + if(last_entry["op"] == "br" or last_entry["op"] == "jmp"): + successors[all_blocks[i][0]] = last_entry["labels"] + elif(last_entry["op"] == "ret"): + successors[all_blocks[i][0]] = ["exit"] + else: + if(i == len(all_blocks) - 1): + successors[all_blocks[i][0]] = ["exit"] + else: + successors[all_blocks[i][0]] = [all_blocks[i + 1][0]] + return successors + +def remove_orphans(all_blocks, cfg): + visited = {} + for block in all_blocks: + visited[block[0]] = False + + for entry in cfg: + for successor in cfg[entry]: + visited[successor] = True + + parsed_blocks = [] + for block in all_blocks: + if visited[block[0]]: + parsed_blocks.append(block) + return parsed_blocks +if __name__ == "__main__": + filename = sys.argv[1] + all_blocks = change_labels(blocks.blocks(filename)) + cfg = build_cfg(all_blocks) + print(cfg) + # print(remove_orphans(all_blocks, cfg)) \ No newline at end of file diff --git a/cs6120/lesson_2/empty.json b/cs6120/lesson_2/empty.json new file mode 100644 index 000000000..2e6257de1 --- /dev/null +++ b/cs6120/lesson_2/empty.json @@ -0,0 +1,3 @@ +{ + "functions": [] +} \ No newline at end of file diff --git a/cs6120/lesson_2/empty.out b/cs6120/lesson_2/empty.out new file mode 100644 index 000000000..e69de29bb diff --git a/cs6120/lesson_2/rot13.json b/cs6120/lesson_2/rot13.json new file mode 100644 index 000000000..e850a195e --- /dev/null +++ b/cs6120/lesson_2/rot13.json @@ -0,0 +1,105 @@ +{ + "functions": [ + { + "args": [ + { + "name": "input", + "type": "int" + } + ], + "instrs": [ + { + "args": [ + "input" + ], + "dest": "aed", + "funcs": [ + "rot" + ], + "op": "call", + "type": "int" + }, + { + "args": [ + "aed" + ], + "op": "print" + } + ], + "name": "main" + }, + { + "args": [ + { + "name": "n", + "type": "int" + } + ], + "instrs": [ + { + "dest": "thirteen", + "op": "const", + "type": "int", + "value": 13 + }, + { + "dest": "twenty_six", + "op": "const", + "type": "int", + "value": 26 + }, + { + "args": [ + "n", + "thirteen" + ], + "dest": "shifted", + "op": "add", + "type": "int" + }, + { + "args": [ + "shifted", + "twenty_six" + ], + "dest": "over", + "op": "ge", + "type": "bool" + }, + { + "args": [ + "over" + ], + "labels": [ + "if", + "else" + ], + "op": "br" + }, + { + "label": "if" + }, + { + "args": [ + "shifted", + "twenty_six" + ], + "dest": "shifted", + "op": "sub", + "type": "int" + }, + { + "label": "else" + }, + { + "args": [ + "shifted" + ], + "op": "ret" + } + ], + "name": "rot", + "type": "int" + } + ] +} diff --git a/cs6120/lesson_2/rot13.out b/cs6120/lesson_2/rot13.out new file mode 100644 index 000000000..8352bc362 --- /dev/null +++ b/cs6120/lesson_2/rot13.out @@ -0,0 +1,2 @@ +main +rot diff --git a/cs6120/lesson_2/turnt.toml b/cs6120/lesson_2/turnt.toml new file mode 100644 index 000000000..ae693c7cc --- /dev/null +++ b/cs6120/lesson_2/turnt.toml @@ -0,0 +1 @@ +command = "python branch_names.py {filename}" \ No newline at end of file diff --git a/docs/tools/bench.md b/docs/tools/bench.md index 1634619d3..0bf3e0426 100644 --- a/docs/tools/bench.md +++ b/docs/tools/bench.md @@ -66,6 +66,7 @@ The current benchmarks are: * `fitsinside`: Output whether or not a rectangle fits inside of another rectangle given the width and height lengths. * `relative-primes`: Print all numbers relatively prime to *n* using [Euclidean algorithm][euclidean_into]. * `riemann`: Prints the left, midpoint, and right [Riemann][riemann] Sums for a specified function, which is the square function in this benchmark. +* `rot13`: Prints the [rot13][rot13] substitution of a character (represented as an integer in the range 0 to 25). * `sieve`: Print all prime numbers up to *n* using the [Sieve of Eratosthenes][sievee]. * `sqrt`: Implements the [Newton–Raphson Method][newton] of approximating the square root of a number to arbitrary precision * `sum-bit`: Print the number of 1-bits in the binary representation of the input integer. @@ -103,6 +104,7 @@ Credit for several of these benchmarks goes to Alexa VanHattum and Gregory Yaune [adler32]: https://en.wikipedia.org/wiki/Adler-32 [uparrow]: https://en.wikipedia.org/wiki/Knuth%27s_up-arrow_notation [riemann]: https://en.wikipedia.org/wiki/Riemann_sum +[rot13]: https://en.wikipedia.org/wiki/ROT13 [primitive_root]: https://en.wikipedia.org/wiki/Primitive_root_modulo_n [mandelbrot]: https://en.wikipedia.org/wiki/Mandelbrot_set [palindrome]: https://en.wikipedia.org/wiki/Palindrome