diff --git a/.gitignore b/.gitignore index 259148f..c8762fb 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,17 @@ +# Build directories +build/ +out/ +cmake-build-*/ + +# Third party dependencies +3rdparty/ + +# IDE specific files +.idea/ +.vscode/ +*.swp +.DS_Store + # Prerequisites *.d @@ -30,3 +44,13 @@ *.exe *.out *.app + +# Windows specific +*.vcxproj +*.vcxproj.filters +*.vcxproj.user +*.sln +[Dd]ebug/ +[Rr]elease/ +x64/ +x86/ diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..40d370a --- /dev/null +++ b/CMakeLists.txt @@ -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() \ No newline at end of file diff --git a/README.md b/README.md index 0b5a629..db51863 100644 --- a/README.md +++ b/README.md @@ -1 +1,55 @@ -# MachOCodeGen \ No newline at end of file +# 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 \ No newline at end of file diff --git a/include/Analyzer.h b/include/Analyzer.h new file mode 100644 index 0000000..4d5cde3 --- /dev/null +++ b/include/Analyzer.h @@ -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 \ No newline at end of file diff --git a/src/Analyzer.cpp b/src/Analyzer.cpp new file mode 100644 index 0000000..3049f40 --- /dev/null +++ b/src/Analyzer.cpp @@ -0,0 +1,24 @@ +#include "llvm/IR/Function.h" +#include "llvm/IR/Instructions.h" +#include +#include + +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"; +} \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..e98f96f --- /dev/null +++ b/src/main.cpp @@ -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 +#include + +int main(int argc, char **argv) { + if (argc < 2) { + std::cerr << "Usage: " << argv[0] << " \n"; + return 1; + } + + // Create LLVM context + llvm::LLVMContext context; + llvm::SMDiagnostic err; + + // Parse the IR file + std::unique_ptr 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; +} \ No newline at end of file diff --git a/tests/test.cpp b/tests/test.cpp new file mode 100644 index 0000000..462e233 --- /dev/null +++ b/tests/test.cpp @@ -0,0 +1,3 @@ +int add(int a, int b) { return a + b; } + +int main() { return add(40, 2); } \ No newline at end of file