Skip to content

Commit

Permalink
Merge pull request #3 from icyphy/llvm16-support
Browse files Browse the repository at this point in the history
LLVM16 support
  • Loading branch information
lsk567 authored Dec 4, 2024
2 parents 015a63d + cda5cba commit ce9d860
Show file tree
Hide file tree
Showing 13 changed files with 70 additions and 92 deletions.
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)

0 comments on commit ce9d860

Please sign in to comment.