1 | Getting Set Up as a CFA Developer |
---|
2 | ================================= |
---|
3 | |
---|
4 | |
---|
5 | Joining the Core Team |
---|
6 | --------------------- |
---|
7 | |
---|
8 | If you are a new student on Peter Buhr's research team (or playing a similar "embedded" role), you need to ensure that Peter provides you with membership/access for: |
---|
9 | - ssh login on plg2.uwaterloo.ca |
---|
10 | - push to the git repo cforall@plg.uwaterloo.ca:software/cfa/cfa-cc |
---|
11 | - log in to the bug tracker (to create/edit tickets that are publicly browsable): https://cforall.uwaterloo.ca/trac |
---|
12 | - receive email notifications for git pushes, ticket edits, and build successes/failures |
---|
13 | - receive email broadcasts of the broader PLG: proglang-research@lists.uwaterloo.ca |
---|
14 | |
---|
15 | Note also the resources: |
---|
16 | - projet's public website: https://cforall.uwaterloo.ca/ |
---|
17 | - common build service, publicly browsable: https://cforall.uwaterloo.ca/jenkins/ |
---|
18 | - It orchestrates build+test on a dozen machines of varying architectures |
---|
19 | - It runs a ~10-min build+test after every push and emails the result |
---|
20 | - It runs a ~1-hour build+test nightly (plus, upon request to Peter) and emails the result |
---|
21 | - It's normal to push a change that was working locally, but have these more thorough tests tell you otherwise. No shame in "breaking the build," just get it fixed. (Usually, roll back your change if a fix will take more than a couple hours, but case-by-case discussion is common.) |
---|
22 | - When more info about a failure is needed than what's in the log attached to the email, it's often findable by browsing the Jenkins website |
---|
23 | - Direct email from you to all individuals in the core team is the best way to ask how something works, what an error message means, or so on. |
---|
24 | |
---|
25 | |
---|
26 | Kicking the tires |
---|
27 | ----------------- |
---|
28 | |
---|
29 | Read and do the instructions in cfa-cc/INSTALL, to get a working CFA compiler built from source. Many members of the core team do this (and much general work) on plg2. |
---|
30 | |
---|
31 | The program `cfa` is the driver, which acts like a command-line stand-in to the `gcc` command. Its source starts from cfa-cc/src/driver/cfa.cc. |
---|
32 | |
---|
33 | The driver runs `cfa-cpp`, which is the actual Cforall to C transpiler, while cfa is a wrapper command which runs the preprocessor, cfa-cc, and then the rest of the gcc compilation chain. The `cfa-cpp` source code starts from cfa-cc/src/main.cpp. |
---|
34 | |
---|
35 | Most CFA programs rely on `libcfa`, the CFA core runtime library. Its source is in `cfa-cc/libcfa/src`. It gets compiled while building CFA, into `(where-ran-configure)/libcfa/x64-debug/src/.libs/libcfa.so` and `libcfathread.so`. Your test programs link with it. |
---|
36 | |
---|
37 | Most CFA programs rely on "the prelude", which is a collection of headers that your test programs implicitly import. Its source is in cfa-cc/libcfa/prelude. It gets preprocessed while building CFA into `(where-ran-configure)/libcfa/x64-debug/prelude`, which is is compiled within your test programs. |
---|
38 | |
---|
39 | A variety of example CFA programs is available in cfa-cc/tests/**/*.cfa. They compile and run in a test-suite invocation as described in cfa-cc/INSTALL, as occurs under a Jenkins build, or as some prefer to run manually: |
---|
40 | pwd # assert in a build folder |
---|
41 | ./tests/test.py --all -j8 |
---|
42 | ./tests/test.py exceptions/hotpotato # just one test |
---|
43 | # see cfa-cc/tests/exceptions/hotpotato.cfa: source code |
---|
44 | # see cfa-cc/tests/exceptions/.expect/hotpotato.txt: running its ./a.out should print this |
---|
45 | |
---|
46 | Manual full test-program compilation, broken into stages: |
---|
47 | |
---|
48 | cfa test.cfa -CFA > test.lowered.c |
---|
49 | gcc -c test.lowered.c |
---|
50 | cfa test.lowered.o # link via our driver, to get libcfa |
---|
51 | ./a.out |
---|
52 | |
---|
53 | Lowering step, abbreviated to be more readable: |
---|
54 | |
---|
55 | cfa test.cfa -CFA -XCFA,-p |
---|
56 | |
---|
57 | Example of examining the CFA lowering at roughly its halfway point: |
---|
58 | |
---|
59 | cfa test.cfa -CFA -XCFA,-p,-Pascodegen,-Pexpranly |
---|
60 | |
---|
61 | -XCFA passes the argument/comma separated arguments to cfa-cpp. Get help on more -XCFA/cfa-cpp arguments: |
---|
62 | |
---|
63 | cfa test.cfa -CFA -XCFA,--help |
---|
64 | cfa-cpp --help |
---|
65 | |
---|
66 | Example of isolating a cfa-cpp invocation on your test program. Most useful for debugging the code under `cfa-cc/src`. The presentation assumes an install in the style that cfa-cc/INSTALL calls "side-by-side," though there are equivalents for all the styles. |
---|
67 | |
---|
68 | ./build/driver/cfa test.cfa -E > test.preprocessed.cfa |
---|
69 | ./build/driver/cfa-cpp test.preprocessed.cfa -p --prelude-dir ./build/libcfa/x64-debug/prelude |
---|
70 | gdb -args ./build/driver/cfa-cpp test.preprocessed.cfa -p --prelude-dir ./build/libcfa/x64-debug/prelude |
---|
71 | |
---|
72 | Debugging the cfa-cpp program is most productive in a "debug" configuration. (Whereas working on libcfa changes is more productive in a cfa-cc/INSTALL "vanilla" configuration.) An example of creating such a configuration, repeating the above gdb invocation within this configuration, and doing a basic tour of cfa-cpp data structures: |
---|
73 | |
---|
74 | mkdir build-gdb |
---|
75 | cd build-gdb |
---|
76 | ../cfa-cc/configure --with-target-hosts=host:debug CXXFLAGS='-O0 -g' |
---|
77 | make -j8 |
---|
78 | gdb -args ./driver/cfa-cpp ../test.preprocessed.cfa -p --prelude-dir ./libcfa/x64-debug/prelude |
---|
79 | |
---|
80 | b ResolvExpr::resolve |
---|
81 | run |
---|
82 | # stopped at breakpoint |
---|
83 | fini |
---|
84 | # in main, at the "rough halfway point" of -Pexpranly |
---|
85 | p transUnit.decls.size() # top-level: preulde+includes+yours |
---|
86 | set $lastDecl = transUnit.decls.back().get() # probably from your code: main? |
---|
87 | call CodeGen::generate( $lastDecl, std::cerr ) # like -XCFA,-Pexpranly,-Pascodegen |
---|
88 | call ast::print( std::cerr, $lastDecl, (Indenter){0,2} ) # like -XCFA,-Pexpranly |
---|
89 | |
---|
90 | # assuming $lastDecl is your program main, with argc/argv declared ... |
---|
91 | p *$lastDecl # assert an ast::FunctionDecl |
---|
92 | p ((ast::FunctionDecl*)$lastDecl)->params.size() # assert 2 |
---|
93 | set $argc_d = ((ast::FunctionDecl*)$lastDecl)->params[0].get() |
---|
94 | call CodeGen::generate( $argc_d, std::cerr ) |
---|
95 | call ast::print( std::cerr, $argc_d, (Indenter){0,2} ) |
---|
96 | |
---|
97 | # digging into argv gives sense of AST's granularity, utility of `call print` over dig-cast-`p` |
---|
98 | set $argv_d = ((ast::FunctionDecl*)$lastDecl)->params[1].get() |
---|
99 | call ast::print( std::cerr, $argv_d, (Indenter){0,2} ) |
---|
100 | p *$argv_d # assert an ast::ObjectDecl |
---|
101 | set $argv_t0 = ((ast::ObjectDecl*)$argv_d)->type.get() |
---|
102 | p *$argv_t0 # assert an ast::PointerType |
---|
103 | set $argv_t1 = ((ast::PointerType*)$argv_t0)->base.get() |
---|
104 | p *$argv_t1 # assert an ast::PointerType |
---|
105 | set $argv_t2 = ((ast::PointerType*)$argv_t1)->base.get() |
---|
106 | p *$argv_t2 # assert an ast::BasicType |
---|
107 | p ((ast::BasicType*)$argv_t2)->kind # assert ast::Char |
---|