util.py 3.51 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# Copyright 2017 The Australian National University
# 
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# 
#     http://www.apache.org/licenses/LICENSE-2.0
# 
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

15
16
import os, subprocess, ctypes, sys;
import struct;
17
18
19

muc = os.environ.get('MUC', 'muc'); #type: str
emit = os.environ.get('MU_EMIT_DIR', 'emit'); #type: str
20
libext = '.dylib' if sys.platform.startswith('darwin') else \
21
22
         '.so'    if sys.platform.startswith('linux') else sys.exit("Unsupported platform"); #type: str
libmu = os.path.join(os.environ.get('MU_ZEBU', os.path.dirname(os.path.dirname(os.getcwd()))),
Javad Ebrahimian Amiri's avatar
Javad Ebrahimian Amiri committed
23
                     'target', os.environ.get('ZEBU_BUILD', 'debug'), 'deps',
24
                     "libmu" + libext); #type: str
25
prelude = """
26
27
28
29
30
31
32
        /*--------------------------------------------------------*/
        .funcsig exit_sig = (int<32>) -> ()
        .typedef exit_type = ufuncptr<exit_sig>
        .const exit <exit_type> = EXTERN "exit"
        .typedef char = int<8>
        .funcsig main_sig = (int<32> uptr<uptr<char>>)->(int<32>)
        /*--------------------------------------------------------*/
33
34
35
36
37
"""

""" Makes a primordial function that calls the given 'main' function (which should have the same signature as a C main function) """
def make_primordial(main): # type: (str) -> str
    return """
38
        /*--------------------------------------------------------*/
39
40
41
42
43
44
        .funcdef primordial <(int<32> uptr<uptr<char>>)->()>
        {
            entry(<int<32>>argc <uptr<uptr<char>>>argv):
                res = CALL <main_sig> """ + main + """(argc argv)
                CCALL #DEFAULT <exit_type exit_sig> exit(res) 
                RET // Unreachable
45
46
47
        }
        /*--------------------------------------------------------*/
        """;
48
49
50
51
52

def get_output_file(name): # type: (str) -> str
    return os.path.join(emit, name);

def execute_muc(bundle, name, primordial=None): # type: (str, str, Optional[str]) -> None
53
    sys.stderr.write(bundle);
54
55
56
57
    muc_proc = subprocess.Popen([muc, "-r"]
        + (["-f", primordial] if primordial is not None else [])
        +  ["/dev/stdin", get_output_file(name)],
        stdin = subprocess.PIPE); #type: subprocess.Popen
58
59
60
61
62
    stdoutdata, stderrdata = muc_proc.communicate(bundle); # Send the bundle to muc
    print("errors:\n\n")
    print(stderrdata);
    print("outputs:\n\n")
    print(stdoutdata);
63
64
    assert (muc_proc.returncode == 0); # Check that muc worked

65
def compile_bundle(bundle, name, main = None): # type: (str, str, Optional[str]) -> None
66
    execute_muc(prelude + bundle + make_primordial(main if main is not None else name), name, "primordial");
67
68

def execute(name, args = []): # type: (str, Optional[List[str]]) -> int
69
70
71
    return subprocess.call([get_output_file(name)] + args);

def load_bundle(bundle, name): # type: (str, str) -> ctypes.CDLL
72
    ctypes.CDLL(libmu, ctypes.RTLD_GLOBAL);
73
    execute_muc(prelude + bundle, name + libext);
74
    return ctypes.CDLL(get_output_file(name + libext), ctypes.RTLD_GLOBAL);
75
76
77
78

def get_function(func, argtypes, restype): # type: (ctypes._FuncPtr) -> (ctypes._FuncPtr)
    func.argtypes = argtypes;
    func.restype = restype;
79
    return func;