Skip to content
Open
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
24 changes: 24 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,17 @@
# Build directories
build/
out/
cmake-build-*/

# Third party dependencies
3rdparty/

# IDE specific files
.idea/
.vscode/
*.swp
.DS_Store

# Prerequisites
*.d

Expand Down Expand Up @@ -30,3 +44,13 @@
*.exe
*.out
*.app

# Windows specific
*.vcxproj
*.vcxproj.filters
*.vcxproj.user
*.sln
[Dd]ebug/
[Rr]elease/
x64/
x86/
82 changes: 82 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
cmake_minimum_required(VERSION 3.13.4)

# Detect OS and set platform-specific variables
if(WIN32)
# Windows: Try to find LLVM in standard install locations
set(LLVM_DIR "C:/Program Files/LLVM/lib/cmake/llvm" CACHE PATH "LLVM installation directory")

# Allow user to override LLVM path through environment variable
if(DEFINED ENV{LLVM_DIR})
set(LLVM_DIR "$ENV{LLVM_DIR}/lib/cmake/llvm")
endif()
else()
# macOS/Linux: Use brew path or system path
execute_process(
COMMAND brew --prefix llvm
OUTPUT_VARIABLE LLVM_BREW_PATH
OUTPUT_STRIP_TRAILING_WHITESPACE
RESULT_VARIABLE BREW_LLVM_RESULT
)

if(BREW_LLVM_RESULT EQUAL 0)
set(LLVM_DIR "${LLVM_BREW_PATH}/lib/cmake/llvm")
# Set compilers for macOS
set(CMAKE_C_COMPILER "${LLVM_BREW_PATH}/bin/clang")
set(CMAKE_CXX_COMPILER "${LLVM_BREW_PATH}/bin/clang++")
endif()
endif()

project(MyLLVMProject)

message(STATUS "Looking for LLVM in: ${LLVM_DIR}")

# Find LLVM package
find_package(LLVM REQUIRED CONFIG)
message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}")
message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}")

# LLVM settings
include_directories(SYSTEM ${LLVM_INCLUDE_DIRS})
link_directories(${LLVM_LIBRARY_DIRS})
add_definitions(${LLVM_DEFINITIONS})

# Include our own headers - make this relative to build directory
include_directories("${CMAKE_SOURCE_DIR}/include") # Quote the path

# Create the executable
add_executable(analyzer
src/main.cpp
src/Analyzer.cpp
)

# Get the LLVM components we need
llvm_map_components_to_libnames(llvm_libs
Core
Support
IRReader
Analysis
)

# Link against LLVM libraries
target_link_libraries(analyzer ${llvm_libs})

# Set C++ standard for all targets
set_target_properties(analyzer PROPERTIES
CXX_STANDARD 17
CXX_STANDARD_REQUIRED ON
)

# Windows-specific settings
if(MSVC)
# Add Windows-specific compiler flags
target_compile_options(analyzer PRIVATE
/W4 # Warning level 4
/EHsc # Enable C++ exceptions
)
else()
# Unix-like compiler flags
target_compile_options(analyzer PRIVATE
-Wall
-Wextra
)
endif()
56 changes: 55 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,55 @@
# MachOCodeGen
# MachOCodeGen

A tool for analyzing LLVM IR using the LLVM framework.

## Prerequisites

### Windows
1. Install LLVM:
```batch
winget install LLVM
```
Or download from [LLVM Releases](https://releases.llvm.org/)

2. Either:
- Install LLVM to the default location (`C:/Program Files/LLVM`), or
- Set the `LLVM_DIR` environment variable to your LLVM installation path

### macOS
1. Install LLVM using Homebrew:
```bash
brew install llvm
```

## Building the Project

### Windows
```batch
mkdir build
cd build
cmake ..
cmake --build .
```

### macOS
```bash
mkdir build
cd build
cmake ..
make
```

## Usage

The analyzer takes an LLVM IR file as input and provides analysis information:

```bash
./analyzer input.ll
```

To generate LLVM IR from C/C++ code:
```bash
clang -S -emit-llvm input.c -o output.ll
```

## Project Structure
16 changes: 16 additions & 0 deletions include/Analyzer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#ifndef ANALYZER_H
#define ANALYZER_H

// Remove forward declaration and include the actual header
#include "llvm/IR/Module.h"

class Analyzer {
public:
explicit Analyzer(llvm::Module *M); // Added semicolon
void analyze(); // Added semicolon

private:
llvm::Module *module; // Added semicolon
}; // Added semicolon

#endif // ANALYZER_H
24 changes: 24 additions & 0 deletions src/Analyzer.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#include "llvm/IR/Function.h"
#include "llvm/IR/Instructions.h"
#include <Analyzer.h>
#include <iostream>

Analyzer::Analyzer(llvm::Module *M) : module(M) {}

void Analyzer::analyze() {
// Count functions and basic blocks
unsigned numFunctions = 0;
unsigned numBasicBlocks = 0;

for (auto &F : *module) {
numFunctions++;

for (auto &BB : F) {
numBasicBlocks++;
}
}

std::cout << "Module Analysis Results:\n"
<< "Number of functions: " << numFunctions << "\n"
<< "Number of basic blocks: " << numBasicBlocks << "\n";
}
39 changes: 39 additions & 0 deletions src/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// LLVM includes
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/IRReader/IRReader.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/raw_ostream.h"

// Local includes
#include "Analyzer.h"

// Standard includes
#include <iostream>
#include <memory>

int main(int argc, char **argv) {
if (argc < 2) {
std::cerr << "Usage: " << argv[0] << " <IR file>\n";
return 1;
}

// Create LLVM context
llvm::LLVMContext context;
llvm::SMDiagnostic err;

// Parse the IR file
std::unique_ptr<llvm::Module> module =
llvm::parseIRFile(argv[1], err, context);

if (!module) {
err.print(argv[0], llvm::errs());
return 1;
}

// Create our analyzer and run it
Analyzer analyzer(module.get());
analyzer.analyze();

return 0;
}
3 changes: 3 additions & 0 deletions tests/test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
int add(int a, int b) { return a + b; }

int main() { return add(40, 2); }