forked from M-Labs/artiq
1
0
Fork 0

compiler: system calls

This commit is contained in:
Sebastien Bourdeauducq 2014-07-04 17:17:01 +02:00
parent c4f49e7dff
commit 71323fb7cd
2 changed files with 50 additions and 15 deletions

View File

@ -61,7 +61,7 @@ def _emit_expr(builder, ns, node):
else: else:
raise NotImplementedError raise NotImplementedError
def _emit_statements(builder, ns, stmts): def _emit_statements(env, builder, ns, stmts):
for stmt in stmts: for stmt in stmts:
if isinstance(stmt, ast.Return): if isinstance(stmt, ast.Return):
val = _emit_expr(builder, ns, stmt.value) val = _emit_expr(builder, ns, stmt.value)
@ -83,11 +83,11 @@ def _emit_statements(builder, ns, stmts):
builder.cbranch(condition, then_block, else_block) builder.cbranch(condition, then_block, else_block)
builder.position_at_end(then_block) builder.position_at_end(then_block)
_emit_statements(builder, ns, stmt.body) _emit_statements(env, builder, ns, stmt.body)
builder.branch(merge_block) builder.branch(merge_block)
builder.position_at_end(else_block) builder.position_at_end(else_block)
_emit_statements(builder, ns, stmt.orelse) _emit_statements(env, builder, ns, stmt.orelse)
builder.branch(merge_block) builder.branch(merge_block)
builder.position_at_end(merge_block) builder.position_at_end(merge_block)
@ -101,19 +101,25 @@ def _emit_statements(builder, ns, stmts):
builder.cbranch(condition, body_block, else_block) builder.cbranch(condition, body_block, else_block)
builder.position_at_end(body_block) builder.position_at_end(body_block)
_emit_statements(builder, ns, stmt.body) _emit_statements(env, builder, ns, stmt.body)
condition = _emit_expr(builder, ns, stmt.test) condition = _emit_expr(builder, ns, stmt.test)
builder.cbranch(condition, body_block, merge_block) builder.cbranch(condition, body_block, merge_block)
builder.position_at_end(else_block) builder.position_at_end(else_block)
_emit_statements(builder, ns, stmt.orelse) _emit_statements(env, builder, ns, stmt.orelse)
builder.branch(merge_block) builder.branch(merge_block)
builder.position_at_end(merge_block) builder.position_at_end(merge_block)
elif isinstance(stmt, ast.Expr) and isinstance(stmt.value, ast.Call):
call = stmt.value
if call.func.id == "syscall":
env.emit_syscall(builder, call.args[0].s, [])
else:
raise NotImplementedError
else: else:
raise NotImplementedError raise NotImplementedError
def _emit_function_def(module, node): def _emit_function_def(env, module, node):
function_type = lc.Type.function(lc.Type.int(), [lc.Type.int()]*len(node.args.args)) function_type = lc.Type.function(lc.Type.int(), [lc.Type.int()]*len(node.args.args))
function = module.add_function(function_type, node.name) function = module.add_function(function_type, node.name)
bb = function.append_basic_block("entry") bb = function.append_basic_block("entry")
@ -124,27 +130,34 @@ def _emit_function_def(module, node):
llvm_arg.name = ast_arg.arg llvm_arg.name = ast_arg.arg
ns.store(builder, llvm_arg, ast_arg.arg) ns.store(builder, llvm_arg, ast_arg.arg)
_emit_statements(builder, ns, node.body) _emit_statements(env, builder, ns, node.body)
if __name__ == "__main__": if __name__ == "__main__":
from llvm import target as lt from llvm import target as lt
from llvm import passes as lp from llvm import passes as lp
import subprocess import subprocess
from artiq.devices import runtime
testcode = """ testcode = """
def is_prime(x): def run():
x = 37
d = 2 d = 2
prime = 1
while d*d <= x: while d*d <= x:
if x % d == 0: if x % d == 0:
return 0 prime = 0
d = d + 1 d = d + 1
return 1 syscall("rpc")
if prime == 1:
syscall("rpc")
return prime
""" """
node = ast.parse(testcode) node = ast.parse(testcode)
fdef = node.body[0] fdef = node.body[0]
my_module = lc.Module.new("my_module") module = lc.Module.new("main")
_emit_function_def(my_module, fdef) _emit_function_def(runtime.Environment(), module, fdef)
pass_manager = lp.PassManager.new() pass_manager = lp.PassManager.new()
pass_manager.add(lp.PASS_MEM2REG) pass_manager.add(lp.PASS_MEM2REG)
@ -152,18 +165,18 @@ def is_prime(x):
pass_manager.add(lp.PASS_REASSOCIATE) pass_manager.add(lp.PASS_REASSOCIATE)
pass_manager.add(lp.PASS_GVN) pass_manager.add(lp.PASS_GVN)
pass_manager.add(lp.PASS_SIMPLIFYCFG) pass_manager.add(lp.PASS_SIMPLIFYCFG)
pass_manager.run(my_module) pass_manager.run(module)
lt.initialize_all() lt.initialize_all()
tm = lt.TargetMachine.new(triple="or1k", cpu="generic") tm = lt.TargetMachine.new(triple="or1k", cpu="generic")
with open("test.out", "wb") as fout: with open("test.out", "wb") as fout:
objfile = tm.emit_object(my_module) objfile = tm.emit_object(module)
fout.write(objfile) fout.write(objfile)
print("=========================") print("=========================")
print(" LLVM IR") print(" LLVM IR")
print("=========================") print("=========================")
print(my_module) print(module)
print("") print("")
print("=========================") print("=========================")

22
artiq/devices/runtime.py Normal file
View File

@ -0,0 +1,22 @@
from llvm import core as lc
syscall_map = {
"rpc": 0,
"rtio_set": 1,
"rtio_sync": 2,
"dds_program": 3,
}
class Environment:
def emit_syscall(self, builder, syscall_name, args):
syscall_nr = syscall_map[syscall_name]
assert(0 <= syscall_nr <= 0xffff)
# FIXME: replace with "l.sys syscall_nr" after the LLVM problems are fixed
opcode = 0x20000000 | syscall_nr
asm_string = "\n".join(".byte 0x{:02x}".format((opcode >> 8*i) & 0xff)
for i in reversed(range(4)))
sc_type = lc.Type.function(lc.Type.void(), [])
asm = lc.InlineAsm.get(sc_type, asm_string, "")
builder.call(asm, [])