Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LLVM16 support #3

Merged
merged 3 commits into from
Dec 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,6 @@ test/**/*gt/*
**/__pycache__
/Dockerfile*
env
build
build
**/*.bc
**/*.ll
38 changes: 20 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,47 +16,40 @@ cd gametime
git submodule update --init --recursive
```

### 2. Install LLVM and Clang (Version 13)
### 2. Install LLVM and Clang (Version 16)

Gametime requires LLVM and Clang version 13. The installation instructions differ slightly between Linux and macOS:
Gametime requires LLVM and Clang version 16. The installation instructions differ slightly between Linux and macOS:

#### On Linux (Ubuntu/Debian):
Update your package manager and install LLVM and Clang version 13:

```bash
sudo apt update
sudo apt install clang-13 llvm-13
sudo apt install clang-16 llvm-16
```

Ensure that version 13 is used by setting it as the default:

```bash
sudo update-alternatives --install /usr/bin/clang clang /usr/bin/clang-13 100
sudo update-alternatives --install /usr/bin/llvm-config llvm-config /usr/bin/llvm-config-13 100
sudo update-alternatives --install /usr/bin/clang clang /usr/bin/clang-16 100
sudo update-alternatives --install /usr/bin/llvm-config llvm-config /usr/bin/llvm-config-16 100
```

#### On macOS:
First, ensure that Homebrew is installed, then install LLVM version 13 using the following commands:
First, ensure that Homebrew is installed, then install LLVM version 16 using the following commands:

```bash
brew install llvm@13
brew install llvm@16
```

After installation, update your `PATH` to include LLVM version 13:

```bash
export PATH="/usr/local/opt/llvm@13/bin:$PATH"
export PATH="/usr/local/opt/llvm@16/bin:$PATH"
```

### 3. Install Extra Dependencies and Local Modules

Install the required Python packages and additional system libraries:

```bash
pip install -e .
pip install -r requirements.txt
```

#### On Linux (Ubuntu/Debian):
Install additional system libraries:

Expand All @@ -71,6 +64,15 @@ Install the additional libraries via Homebrew:
brew install graphviz
```

#### Install Python dependencies:

Install the required Python packages and additional system libraries:

```bash
pip install -e .
pip install -r requirements.txt
```

If you are having trouble installing pygraphviz on macOS try the following: [StackOverflow](https://stackoverflow.com/questions/69970147/how-do-i-resolve-the-pygraphviz-error-on-mac-os)

### 4. Install KLEE
Expand All @@ -89,7 +91,7 @@ Each test requires a YAML configuration file. Ensure that your YAML file is corr

### 2. Create a Test Class

Navigate to the `wcet.py` file and create a new test class based on one of the available backend configurations. Specify the path to your YAML configuration file in the `config_path` attribute.
Navigate to the `wcet_test.py` file and create a new test class based on one of the available backend configurations. Specify the path to your YAML configuration file in the `config_path` attribute.

#### Example:

Expand All @@ -100,7 +102,7 @@ class TestBinarysearchARM(TestARMBackend):

### 3. Add the Test Class to the Main Function

In the `main` function of `wcet.py`, add your newly created test class to the suite for execution.
In the `main` function of `wcet_test.py`, add your newly created test class to the suite for execution.

#### Example:

Expand All @@ -113,7 +115,7 @@ suite.addTests(loader.loadTestsFromTestCase(TestBinarysearchARM))
Run the test using the following command:

```bash
python wcet.py
python wcet_test.py
```

---
Expand Down
52 changes: 22 additions & 30 deletions src/clang_helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from defaults import logger
from file_helper import remove_files
from project_configuration import ProjectConfiguration
import command_utils


def compile_to_llvm_for_exec(c_filepath: str, output_file_folder: str, output_name: str, extra_libs: List[str]=[], extra_flags: List[str]=[], readable: bool = False) -> str:
Expand Down Expand Up @@ -40,13 +41,13 @@ def compile_to_llvm_for_exec(c_filepath: str, output_file_folder: str, output_na
commands: List[str] = ["clang", "-emit-llvm", "-O0", "-o", output_file, "-c", file_to_compile] + extra_flags
for lib in extra_libs:
commands.append(f"-I{lib}")
subprocess.run(commands, check=True)
command_utils.run(commands)

if readable:
# translate for .ll automatically.
ll_output_file: str = os.path.join(output_file_folder, f"{output_name}.ll")
commands = ["llvm-dis", output_file, "-o", ll_output_file]
subprocess.run(commands, check=True)
command_utils.run(commands)

return output_file

Expand Down Expand Up @@ -81,16 +82,18 @@ def compile_to_llvm_for_analysis(c_filepath: str , output_file_folder: str, outp
file_to_compile: str = c_filepath
output_file: str = os.path.join(output_file_folder, f"{output_name}.bc")

commands: List[str] = ["clang", "-emit-llvm", "-Xclang","-disable-O0-optnone", "-c", file_to_compile, "-o", output_file] + extra_flags
# "-Wno-implicit-function-declaration" is required so that clang
# does not report "undeclared function '__assert_fail'"
commands: List[str] = ["clang", "-emit-llvm", "-Xclang","-disable-O0-optnone", "-Wno-implicit-function-declaration", "-c", file_to_compile, "-o", output_file] + extra_flags
for lib in extra_libs:
commands.append(f"-I{lib}")
subprocess.run(commands, check=True)
command_utils.run(commands, shell=True)

if readable:
# translate for .ll automatically. (optional)
ll_output_file: str = os.path.join(output_file_folder, f"{output_name}.ll")
commands = ["llvm-dis", output_file, "-o", ll_output_file]
subprocess.run(commands, check=True)
command_utils.run(commands)
return output_file

def bc_to_executable(bc_filepath: str, output_folder: str, output_name: str, extra_libs: List[str]=[], extra_flags: List[str]=[]) -> str:
Expand Down Expand Up @@ -123,7 +126,7 @@ def bc_to_executable(bc_filepath: str, output_folder: str, output_name: str, ext
clang_commands.extend(["-I", lib])

# Run clang to compile the bitcode into an executable
subprocess.run(clang_commands, check=True)
command_utils.run(clang_commands)

return executable_file

Expand All @@ -149,7 +152,7 @@ def dump_object(object_filepath: str, output_folder: str, output_name: str) -> s
output_file: str = os.path.join(output_folder, f"{output_name}.dmp")

commands: List[str] = ["riscv32-unknown-elf-objdump", "--target=riscv32", "-march=rv32i", object_filepath, "-c", "-o", output_file]
subprocess.check_call(commands)
command_utils.run(commands)
return output_file

def generate_dot_file(bc_filename: str, bc_file_folder: str, output_name: str = "main") -> str:
Expand All @@ -172,8 +175,8 @@ def generate_dot_file(bc_filename: str, bc_file_folder: str, output_name: str =
output_file: str = f".{output_name}.dot"
cur_cwd: str = os.getcwd()
os.chdir(bc_file_folder) # opt generates .dot in cwd
commands: List[str] = ["opt", "-dot-cfg", "-S", "-enable-new-pm=0","-disable-output", bc_filename ]
subprocess.check_call(commands)
commands: List[str] = ["opt", "-passes=dot-cfg", "-S", "-disable-output", bc_filename]
command_utils.run(commands)
os.chdir(cur_cwd)
return output_file

Expand Down Expand Up @@ -204,12 +207,12 @@ def inline_functions(bc_filepath: str, output_file_folder: str, output_name: str
output_file: str = os.path.join(output_file_folder, f"{output_name}.bc")

commands: List[str] = ["opt",
"-always-inline",
"-inline", "-inline-threshold=10000000",
"-passes=\"always-inline,inline\""
"-inline-threshold=10000000",
"-S", bc_filepath,
"-o", output_file]

logger.info(subprocess.run(commands, check=True))
command_utils.run(commands)
return output_file


Expand Down Expand Up @@ -241,27 +244,16 @@ def unroll_loops(bc_filepath: str, output_file_folder: str, output_name: str, pr
# return bc_filepath
output_file: str = os.path.join(output_file_folder, f"{output_name}.bc")

# Related but unused passes:
# -unroll-threshold=10000000, -unroll-count=4,
# -unroll-allow-partial, -instcombine,
# -reassociate, -indvars, -mem2reg
commands: List[str] = ["opt",
# "-mem2reg",
"-simplifycfg",
"-loops",
"-lcssa",
"-loop-simplify",
"-loop-rotate",
"-indvars",
"-loop-unroll",
"-simplifycfg",
# "-unroll-threshold=10000000",
# "-unroll-count=4",
# "-unroll-allow-partial",
# "-instcombine",
# "-reassociate",
# "-indvars",
"-passes='simplifycfg,loops,lcssa,loop-simplify,loop-rotate,indvars,loop-unroll'"
"-S", bc_filepath,
# "-o", temp_output_file]
"-o", output_file]

logger.info(subprocess.run(commands, check=True))
command_utils.run(commands)

return output_file

Expand Down
12 changes: 12 additions & 0 deletions src/command_utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import subprocess
import sys

def run(command, shell=False):
print(f"==> Executing command: {' '.join(command)}")
result = subprocess.run(command, shell, check=True)
if result.returncode != 0:
print(f"Error running command: {command}")
print(result.stdout)
print(result.stderr)
sys.exit(1)
return result.stdout
2 changes: 1 addition & 1 deletion src/inliner.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ def assemble_bitcode(input_file, output_file):
run_command(f"llvm-as {input_file} -o {output_file}")

def inline_bitcode(input_file, output_file):
run_command(f"opt -always-inline -inline -inline-threshold=10000000 {input_file} -o {output_file}")
run_command(f"opt -passes=\"always-inline,inline\" -inline-threshold=10000000 {input_file} -o {output_file}")

def generate_cfg(input_file):
run_command(f"opt -dot-cfg {input_file}")
Expand Down
1 change: 1 addition & 0 deletions src/smt_solver/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
modify_bitcode
Binary file removed src/smt_solver/modify_bitcode
Binary file not shown.
5 changes: 2 additions & 3 deletions src/unroller.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,14 @@ def unroll_llvm_ir(input_ir, output_ir):
"""
Generate LLVM Intermediate Representation (.ll file) from LLVM bitcode.
"""
command = f"opt -loop-unroll -S {input_ir} -o {output_ir}"
command = f"opt -passes=loop-unroll -S {input_ir} -o {output_ir}"
run_command(command, f"Generating LLVM IR from {input_ir}")


def generate_llvm_dag(output_bc):
"""
Generate LLVM DAG (.dot file) using opt.
"""
command = f"opt -dot-cfg -S -enable-new-pm=0 -disable-output {output_bc}"
command = f"opt -passes=dot-cfg -S -disable-output {output_bc}"
run_command(command, f"Generating LLVM DAG from bitcode {output_bc}")

def modify_loop_branches_to_next_block(input_file_path, output_file_path):
Expand Down
2 changes: 1 addition & 1 deletion test/tacle_test/programs/ext_func/ext_lib_test/inline.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ def assemble_bitcode(input_file, output_file):
run_command(f"llvm-as {input_file} -o {output_file}")

def inline_functions(input_file, output_file):
run_command(f"opt -always-inline -inline -inline-threshold=10000000 {input_file} -o {output_file}")
run_command(f"opt -passes=always-inline,inline -inline-threshold=10000000 {input_file} -o {output_file}")

def generate_cfg(input_file):
run_command(f"opt -dot-cfg {input_file}")
Expand Down
1 change: 0 additions & 1 deletion test/tacle_test/programs/if_elif_else/helper.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
#include "helper.h"
#include <stdio.h>

int abs(int x) {
Expand Down
34 changes: 1 addition & 33 deletions test/tacle_test/programs/if_elif_else/if_elif_else.c
Original file line number Diff line number Diff line change
@@ -1,40 +1,8 @@
#include <stdint.h>
#include <stdbool.h>
#include <unistd.h>
#include <stdio.h>
#include </Users/abdallaeltayeb/Desktop/Gamtime_project/gametime/test/tacle_test/programs/if_elif_else/helper.h>

// int test (int x) {
// // if (x < 0 && b < 0) {
// // // sleep(5);
// // return 1;
// // } else if (x < 0 && b == 0) {
// // return 2;
// // } else if (x < 0 && b > 0) {
// // return 3;
// // } else if (x == 0 && b < 0) {
// // return 4;
// // // } else if (x == 0 && b == 0) {
// // // return 5;
// // // } else if (x == 0 && b > 0) {
// // // return 6;
// // // } else if (x > 0 && b < 0) {
// // // return 7;
// // // } else if (x > 0 && b == 0) {
// // // return 8;
// // } else {
// // return 9;
// // }
// if(x > 0) {
// return 1;
// } else {
// return 0;
// }
// }

// int abs(int x) {
// return x >= 0 ? x : -x;
// }
int abs(int x);

int test(int x){
if (abs(x) == 4) {
Expand Down
4 changes: 2 additions & 2 deletions test/tacle_test/programs/loops/convert.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ def unroll_llvm_ir(input_ir, output_ir):
"""
Generate LLVM Intermediate Representation (.ll file) from LLVM bitcode.
"""
command = f"opt -loop-unroll -S {input_ir} -o {output_ir}"
command = f"opt -passes=loop-unroll -S {input_ir} -o {output_ir}"
run_command(command, f"Generating LLVM IR from {input_ir}")


Expand All @@ -42,7 +42,7 @@ def generate_llvm_dag(output_bc):
Generate LLVM DAG (.dot file) using llc and opt tools.
"""
# Use llc to create DAG
command = f"opt -dot-cfg -S -enable-new-pm=0 -disable-output {output_bc}"
command = f"opt -passes=dot-cfg -S -disable-output {output_bc}"
run_command(command, f"Generating LLVM DAG from bitcode {output_bc}")

def modify_loop_branches_to_next_block(input_file_path, output_file_path):
Expand Down
7 changes: 5 additions & 2 deletions test/tacle_test/wcet_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@ class TestBitcnt2Flexpret(TestFlexpretBackend):
config_path = "./programs/bitcount/config.yaml"
class TestBitcnt2X86(TestX86Backend):
config_path = "./programs/bitcount/config.yaml"
class TestBitcnt2ARM(TestARMBackend):
config_path = "./programs/bitcount/config.yaml"



Expand Down Expand Up @@ -127,9 +129,10 @@ class TestCountNegativeARM(TestARMBackend):
# suite.addTests(loader.loadTestsFromTestCase(TestPrimeFlexpret))
# suite.addTests(loader.loadTestsFromTestCase(TestIfElifElseX86))
# suite.addTests(loader.loadTestsFromTestCase(TestBinarysearchARM))
# suite.addTests(loader.loadTestsFromTestCase(TestIfElifElseARM))
suite.addTests(loader.loadTestsFromTestCase(TestIfElifElseARM))
# suite.addTests(loader.loadTestsFromTestCase(TestBitcnt2ARM))
# suite.addTests(loader.loadTestsFromTestCase(TestPrimeARM))
suite.addTests(loader.loadTestsFromTestCase(TestCountNegativeARM))
# suite.addTests(loader.loadTestsFromTestCase(TestCountNegativeARM))

runner = unittest.TextTestRunner()
runner.run(suite)
Loading