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
2 changes: 2 additions & 0 deletions .clang-format
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
BasedOnStyle: LLVM
LineEnding: LF
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,4 @@ __pycache__

# Build folder
build/
llvm-project/
33 changes: 33 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# LLVM-CBE Build Instructions

## Install CMake (if needed)

```bash
curl -L -O https://github.com/Kitware/CMake/releases/download/v3.30.0/cmake-3.30.0-linux-x86_64.tar.gz
tar -xzf cmake-3.30.0-linux-x86_64.tar.gz
export PATH=$PWD/cmake-3.30.0-linux-x86_64/bin:$PATH
```

## Build LLVM (if needed)

```bash
git clone --single-branch --branch llvmorg-20.1.8 --depth 1 https://github.com/llvm/llvm-project.git
cd llvm-project
cmake -S llvm -B build -G "Ninja" -DCMAKE_BUILD_TYPE=Debug -DLLVM_ENABLE_PROJECTS="clang" -DLLVM_ENABLE_ASSERTIONS=ON -DBUILD_SHARED_LIBS=ON
ninja
```

## Run Tests

### pytest
```bash
cd /home/vtjnash/llvm-cbe
pip install pytest pytest-xdist
pytest -n 4
```

### Unit tests
```bash
cd /home/vtjnash/llvm-project/llvm/build
make CBEUnitTests && projects/llvm-cbe/unittests/CWriterTest
```
3 changes: 3 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,13 @@ if (NOT DEFINED LLVM_VERSION_MAJOR)
include(AddLLVM)

set (CMAKE_CXX_STANDARD 17)
else()
set (USE_SYSTEM_LLVM 0)
endif()

add_subdirectory(lib)
add_subdirectory(tools)
add_subdirectory(clang-plugin)

if( LLVM_INCLUDE_TESTS )
add_subdirectory(unittests)
Expand Down
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ llvm-cbe

This LLVM C backend has been resurrected by Julia Computing with various improvements.

See clang-plugin/README for an enhanced version which provides much more reliable support for linking the output against existing C libraries.
Linking against C++ libraries (or other non-C front-ends ABIs) is not likely to be reliable,
unless it has been defined in terms of a C ABI (such as GCC's Itanium ABI that it uses for most C++ code).

Installation instructions
=========================

Expand Down
91 changes: 91 additions & 0 deletions clang-plugin/CBackend.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
//===-- CBackend.cpp - C Backend ABI Plugin ------------------------------===//
//
// Loadable plugin that provides a type-preserving ABI for LLVM C backend.
// Load with: clang -Xclang -load -Xclang CBackendPlugin.so
//
// Triple format: llvm32-<os>[-<env>] or llvm64-<os>[-<env>]
// e.g. llvm32-linux-gnu, llvm64-linux-gnu, llvm64-darwin
//
//===----------------------------------------------------------------------===//

#include "ABIInfo.h"
#include "ABIInfoImpl.h"
#include "TargetInfo.h"
#include "clang/CodeGen/CGFunctionInfo.h"
#include "llvm/Support/Compiler.h"
#include "llvm/TargetParser/Triple.h"

using namespace clang;
using namespace clang::CodeGen;

namespace {

class CBackendABIInfo : public ABIInfo {
public:
CBackendABIInfo(CodeGenTypes &CGT) : ABIInfo(CGT) {}

ABIArgInfo classifyReturnType(QualType RetTy) const {
if (RetTy->isVoidType())
return ABIArgInfo::getIgnore();
if (RetTy->isSignedIntegerOrEnumerationType())
return ABIArgInfo::getSignExtend(RetTy);
else if (RetTy->isUnsignedIntegerOrEnumerationType())
return ABIArgInfo::getZeroExtend(RetTy);
return ABIArgInfo::getDirect(nullptr, 0, nullptr, /*CanBeFlattened*/ false);
}

ABIArgInfo classifyArgumentType(QualType Ty) const {
Ty = useFirstFieldIfTransparentUnion(Ty);
if (Ty->isVoidType())
return ABIArgInfo::getIgnore();
if (Ty->isSignedIntegerOrEnumerationType())
return ABIArgInfo::getSignExtend(Ty);
else if (Ty->isUnsignedIntegerOrEnumerationType())
return ABIArgInfo::getZeroExtend(Ty);
if (isAggregateTypeForABI(Ty)) {
// Structures with either a non-trivial destructor or a non-trivial
// copy constructor are always indirect.
if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI())) {
return getNaturalAlignIndirect(Ty, /*ByVal=*/RAA ==
CGCXXABI::RAA_DirectInMemory);
}
}
return ABIArgInfo::getDirect(nullptr, 0, nullptr, /*CanBeFlattened*/ false);
}

void computeInfo(CGFunctionInfo &FI) const override {
if (!::classifyReturnType(getCXXABI(), FI, *this))
FI.getReturnInfo() = classifyReturnType(FI.getReturnType());
for (auto &Arg : FI.arguments())
Arg.info = classifyArgumentType(Arg.type);
}

RValue EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty,
AggValueSlot Slot) const override {
return emitVoidPtrVAArg(CGF, VAListAddr, Ty, /*IsIndirect=*/false,
CGF.getContext().getTypeInfoInChars(Ty),
CharUnits::fromQuantity(8),
/*AllowHigherAlign=*/true, Slot);
}
};

class CBackendTargetCodeGenInfo : public TargetCodeGenInfo {
public:
CBackendTargetCodeGenInfo(CodeGenTypes &CGT)
: TargetCodeGenInfo(std::make_unique<CBackendABIInfo>(CGT)) {}
};
} // namespace

namespace clang {
namespace CodeGen {
inline std::unique_ptr<TargetCodeGenInfo>
createCBackendTargetCodeGenInfo(CodeGenModule &CGM) {
return std::make_unique<CBackendTargetCodeGenInfo>(CGM.getTypes());
}
} // namespace CodeGen
} // namespace clang

extern "C" LLVM_ABI_EXPORT void *getCBackendABIForTarget(const llvm::Triple *T,
CodeGenModule *CGM) {
return createCBackendTargetCodeGenInfo(*CGM).release();
}
35 changes: 35 additions & 0 deletions clang-plugin/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
IF (NOT DEFINED LLVM_VERSION_MAJOR)
# Standalone build: requires both LLVM and Clang CMake packages
project(CBackendPlugin)
cmake_minimum_required(VERSION 3.20.0)
find_package(LLVM 20.1 REQUIRED CONFIG)
find_package(Clang REQUIRED CONFIG)
list(APPEND CMAKE_MODULE_PATH "${LLVM_CMAKE_DIR}")
include(AddLLVM)
set(CMAKE_CXX_STANDARD 17)
include_directories(${LLVM_INCLUDE_DIRS} ${CLANG_INCLUDE_DIRS})
add_definitions(${LLVM_DEFINITIONS})
else()
find_package(Clang REQUIRED CONFIG)
include_directories(${CLANG_INCLUDE_DIRS})
endif()

# Internal Clang CodeGen headers (ABIInfo.h, TargetInfo.h, etc.) are not
# exported; derive path from the LLVM source include directory.
get_filename_component(_llvm_src "${LLVM_MAIN_INCLUDE_DIR}" DIRECTORY)
include_directories(${_llvm_src}/../clang/lib/CodeGen)

add_llvm_library(CBackendPlugin MODULE
CBackend.cpp

LINK_LIBS
clangAST
clangBasic
clangCodeGen
LLVMSupport
)

# Plugins must not have undefined symbols
set_target_properties(CBackendPlugin PROPERTIES
CXX_VISIBILITY_PRESET hidden
)
Loading
Loading