Skip to content

Commit

Permalink
Merge pull request #10 from czgdp1807/lc_12
Browse files Browse the repository at this point in the history
Use minimal version of ``evaluator.h`` for LC
  • Loading branch information
czgdp1807 authored Dec 13, 2023
2 parents f9d6e82 + 7af92a6 commit 85411b5
Show file tree
Hide file tree
Showing 8 changed files with 335 additions and 37 deletions.
12 changes: 0 additions & 12 deletions .github/workflows/CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,9 @@ jobs:
submodules: recursive

- uses: mamba-org/provision-with-micromamba@main
if: contains(matrix.os, 'ubuntu')
with:
environment-file: environment_unix.yml

- uses: mamba-org/provision-with-micromamba@main
if: contains(matrix.os, 'macos')
with:
environment-file: environment_macos.yml

- uses: hendrikmuhs/ccache-action@main
with:
variant: sccache
Expand Down Expand Up @@ -78,12 +72,6 @@ jobs:
lc examples/expr2.c --backend llvm --extra-arg="-Isrc/runtime/include" -o llvm_o -c --
ls -1
- name: Test3 (macOS)
shell: bash -l -e {0}
if: contains(matrix.os, 'macos')
run: |
which clang
# Test including iostream and span headers
lc tests/span_01.cpp --ast-dump --ast-dump-file="tests/span_01.ast" --extra-arg="-std=c++20" --
cat tests/span_01.ast
13 changes: 0 additions & 13 deletions environment_macos.yml

This file was deleted.

17 changes: 9 additions & 8 deletions environment_unix.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@ name: lc
channels:
- conda-forge
dependencies:
- cmake
- llvmdev=15.0.6
- clangdev=15.0.6
- make
- zlib
- git
- python=3.11.0
- toml
- cmake=3.27.9
- llvmdev=16.0.6
- clangdev=16.0.6
- compilers=1.7.0
- make=4.3
- zlib=1.2.13
- git=2.43.0
- python=3.12.0
- toml=0.10.2
2 changes: 1 addition & 1 deletion src/bin/lc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
#include <libasr/assert.h>
#include <libasr/pass/pass_manager.h>
#include <libasr/pickle.h>
#include <libasr/codegen/evaluator.h>
#include <libasr/codegen/c_evaluator.h>
#include <libasr/codegen/asr_to_c.h>
#include <libasr/codegen/asr_to_cpp.h>
#include <libasr/codegen/asr_to_fortran.h>
Expand Down
4 changes: 2 additions & 2 deletions src/libasr/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -79,14 +79,14 @@ set(SRC
)
if (WITH_LLVM)
set(SRC ${SRC}
codegen/evaluator.cpp
codegen/c_evaluator.cpp
codegen/asr_to_llvm.cpp
codegen/llvm_array_utils.cpp
codegen/llvm_utils.cpp
)
# We use deprecated API in LLVM, so we disable the warning until we upgrade
if (NOT MSVC)
set_source_files_properties(codegen/evaluator.cpp PROPERTIES
set_source_files_properties(codegen/c_evaluator.cpp PROPERTIES
COMPILE_FLAGS -Wno-deprecated-declarations)
set_source_files_properties(codegen/asr_to_llvm.cpp PROPERTIES
COMPILE_FLAGS -Wno-deprecated-declarations)
Expand Down
2 changes: 1 addition & 1 deletion src/libasr/codegen/asr_to_llvm.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
#define LFORTRAN_ASR_TO_LLVM_H

#include <libasr/asr.h>
#include <libasr/codegen/evaluator.h>
#include <libasr/codegen/c_evaluator.h>
#include <libasr/pass/pass_manager.h>

namespace LCompilers {
Expand Down
266 changes: 266 additions & 0 deletions src/libasr/codegen/c_evaluator.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,266 @@
#include <iostream>
#include <fstream>

#include <llvm/IR/LLVMContext.h>
#include <llvm/ADT/STLExtras.h>
#include <llvm/Analysis/Passes.h>
#include <llvm/Analysis/TargetTransformInfo.h>
#include <llvm/Analysis/TargetLibraryInfo.h>
#include <llvm/ExecutionEngine/ExecutionEngine.h>
#include <llvm/ExecutionEngine/GenericValue.h>
#include <llvm/ExecutionEngine/MCJIT.h>
#include <llvm/IR/Argument.h>
#include <llvm/IR/Attributes.h>
#include <llvm/IR/BasicBlock.h>
#include <llvm/IR/Constants.h>
#include <llvm/IR/DerivedTypes.h>
#include <llvm/IR/Function.h>
#include <llvm/IR/IRBuilder.h>
#include <llvm/IR/Instructions.h>
#include <llvm/IR/Intrinsics.h>
#include <llvm/IR/LegacyPassManager.h>
#include <llvm/IR/Module.h>
#include <llvm/IR/Type.h>
#include <llvm/Support/Casting.h>
#include <llvm/Support/ManagedStatic.h>
#include <llvm/Support/TargetSelect.h>
#include <llvm/Support/raw_ostream.h>
#include <llvm/ADT/APFloat.h>
#include <llvm/ADT/STLExtras.h>
#include <llvm/IR/Verifier.h>
#include <llvm/Support/TargetSelect.h>
#include <llvm/Target/TargetMachine.h>
#include <llvm/Transforms/Scalar.h>
#include <llvm/Transforms/Scalar/GVN.h>
#include <llvm/Transforms/Scalar/InstSimplifyPass.h>
#include <llvm/Transforms/Vectorize.h>
#include <llvm/Transforms/IPO.h>
#include <llvm/Transforms/IPO/AlwaysInliner.h>
#include <llvm/Transforms/IPO/PassManagerBuilder.h>
#include <llvm/Transforms/Instrumentation/AddressSanitizer.h>
#include <llvm/Transforms/Instrumentation/ThreadSanitizer.h>
#include <llvm/Transforms/InstCombine/InstCombine.h>
#include <llvm/ExecutionEngine/ObjectCache.h>
#include <llvm/Support/CommandLine.h>
#include <llvm/Support/FileSystem.h>
#include <llvm/Support/Path.h>
#include <llvm/AsmParser/Parser.h>
#include <llvm/Support/SourceMgr.h>
#include <llvm/ADT/StringRef.h>
#include <llvm/Target/TargetOptions.h>
#if LLVM_VERSION_MAJOR >= 14
# include <llvm/MC/TargetRegistry.h>
#else
# include <llvm/Support/TargetRegistry.h>
#endif
#include <llvm/Support/Host.h>

#include <libasr/codegen/c_evaluator.h>
#include <libasr/codegen/asr_to_llvm.h>
#include <libasr/codegen/asr_to_cpp.h>
#include <libasr/exception.h>
#include <libasr/asr.h>
#include <libasr/string_utils.h>


namespace LCompilers {

// Extracts the integer from APInt.
// APInt does not seem to have this functionality, so we implement it here.
uint64_t APInt_getint(const llvm::APInt &i) {
// The APInt::isSingleWord() is private, but we can emulate it:
bool isSingleWord = !i.needsCleanup();
if (isSingleWord) {
return *i.getRawData();
} else {
throw std::runtime_error("APInt too large to fit uint64_t");
}
}

LLVMModule::LLVMModule(std::unique_ptr<llvm::Module> m)
{
m_m = std::move(m);
}

LLVMModule::~LLVMModule() = default;

std::string LLVMModule::str()
{
return LLVMEvaluator::module_to_string(*m_m);
}

std::string LLVMModule::get_return_type(const std::string &fn_name)
{
llvm::Module *m = m_m.get();
llvm::Function *fn = m->getFunction(fn_name);
if (!fn) {
return "none";
}
llvm::Type *type = fn->getReturnType();
if (type->isFloatTy()) {
return "real4";
} else if (type->isDoubleTy()) {
return "real8";
} else if (type->isIntegerTy(32)) {
return "integer4";
} else if (type->isIntegerTy(64)) {
return "integer8";
} else if (type->isStructTy()) {
llvm::StructType *st = llvm::cast<llvm::StructType>(type);
if (st->hasName()) {
if (startswith(std::string(st->getName()), "complex_4")) {
return "complex4";
} else if (startswith(std::string(st->getName()), "complex_8")) {
return "complex8";
} else {
throw LCompilersException("LLVMModule::get_return_type(): Struct return type `" + std::string(st->getName()) + "` not supported");
}
} else {
throw LCompilersException("LLVMModule::get_return_type(): Noname struct return type not supported");
}
} else if (type->isVectorTy()) {
// Used for passing complex_4 on some platforms
return "complex4";
} else if (type->isVoidTy()) {
return "void";
} else {
throw LCompilersException("LLVMModule::get_return_type(): Return type not supported");
}
}

extern "C" {

float _lfortran_stan(float x);

}

#if LLVM_VERSION_MAJOR >= 16
# define RM_OPTIONAL_TYPE std::optional
#else
# define RM_OPTIONAL_TYPE llvm::Optional
#endif

LLVMEvaluator::LLVMEvaluator(const std::string &t)
{
llvm::InitializeNativeTarget();
llvm::InitializeNativeTargetAsmPrinter();
llvm::InitializeNativeTargetAsmParser();

#ifdef HAVE_TARGET_AARCH64
LLVMInitializeAArch64Target();
LLVMInitializeAArch64TargetInfo();
LLVMInitializeAArch64TargetMC();
LLVMInitializeAArch64AsmPrinter();
LLVMInitializeAArch64AsmParser();
#endif
#ifdef HAVE_TARGET_X86
LLVMInitializeX86Target();
LLVMInitializeX86TargetInfo();
LLVMInitializeX86TargetMC();
LLVMInitializeX86AsmPrinter();
LLVMInitializeX86AsmParser();
#endif
#ifdef HAVE_TARGET_WASM
LLVMInitializeWebAssemblyTarget();
LLVMInitializeWebAssemblyTargetInfo();
LLVMInitializeWebAssemblyTargetMC();
LLVMInitializeWebAssemblyAsmPrinter();
LLVMInitializeWebAssemblyAsmParser();
#endif

context = std::make_unique<llvm::LLVMContext>();

if (t != "")
target_triple = t;
else
target_triple = LLVMGetDefaultTargetTriple();

std::string Error;
const llvm::Target *target = llvm::TargetRegistry::lookupTarget(target_triple, Error);
if (!target) {
throw LCompilersException(Error);
}
std::string CPU = "generic";
std::string features = "";
llvm::TargetOptions opt;
RM_OPTIONAL_TYPE<llvm::Reloc::Model> RM = llvm::Reloc::Model::PIC_;
TM = target->createTargetMachine(target_triple, CPU, features, opt, RM);

_lfortran_stan(0.5);
}

LLVMEvaluator::~LLVMEvaluator()
{
context.reset();
}

void LLVMEvaluator::save_object_file(llvm::Module &m, const std::string &filename) {
m.setTargetTriple(target_triple);
m.setDataLayout(TM->createDataLayout());

llvm::legacy::PassManager pass;
llvm::CodeGenFileType ft = llvm::CGFT_ObjectFile;
std::error_code EC;
llvm::raw_fd_ostream dest(filename, EC, llvm::sys::fs::OF_None);
if (EC) {
throw std::runtime_error("raw_fd_ostream failed");
}
if (TM->addPassesToEmitFile(pass, dest, nullptr, ft)) {
throw std::runtime_error("TargetMachine can't emit a file of this type");
}
pass.run(m);
dest.flush();
}

void LLVMEvaluator::opt(llvm::Module &m) {
m.setTargetTriple(target_triple);
m.setDataLayout(TM->createDataLayout());

llvm::legacy::PassManager mpm;
mpm.add(new llvm::TargetLibraryInfoWrapperPass(TM->getTargetTriple()));
mpm.add(llvm::createTargetTransformInfoWrapperPass(TM->getTargetIRAnalysis()));
llvm::legacy::FunctionPassManager fpm(&m);
fpm.add(llvm::createTargetTransformInfoWrapperPass(TM->getTargetIRAnalysis()));

int optLevel = 3;
int sizeLevel = 0;
llvm::PassManagerBuilder builder;
builder.OptLevel = optLevel;
builder.SizeLevel = sizeLevel;
builder.Inliner = llvm::createFunctionInliningPass(optLevel, sizeLevel,
false);
builder.DisableUnrollLoops = false;
builder.LoopVectorize = true;
builder.SLPVectorize = true;
builder.populateFunctionPassManager(fpm);
builder.populateModulePassManager(mpm);

fpm.doInitialization();
for (llvm::Function &func : m) {
fpm.run(func);
}
fpm.doFinalization();

mpm.add(llvm::createVerifierPass());
mpm.run(m);
}

std::string LLVMEvaluator::module_to_string(llvm::Module &m) {
std::string buf;
llvm::raw_string_ostream os(buf);
m.print(os, nullptr);
os.flush();
return buf;
}

llvm::LLVMContext &LLVMEvaluator::get_context()
{
return *context;
}

std::string LLVMEvaluator::get_default_target_triple()
{
return llvm::sys::getDefaultTargetTriple();
}

} // namespace LCompilers
Loading

0 comments on commit 85411b5

Please sign in to comment.