Skip to content

Commit

Permalink
Finishing minimum compilation on windows.
Browse files Browse the repository at this point in the history
  • Loading branch information
mason-bially committed Jun 11, 2018
1 parent 6d19d85 commit b2ba0d7
Show file tree
Hide file tree
Showing 6 changed files with 360 additions and 86 deletions.
11 changes: 5 additions & 6 deletions src/backendllvm/LlvmBackend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,17 @@ CRAFT_DEFINE(LlvmBackend)
_.defaults();
}

std::string LlvmBackend::mangledName(instance<SBindable> bindable)
std::string LlvmBackend::mangledName(instance<SBindable> bindable, std::string const& postFix)
{
auto binding = bindable->getBinding();
auto module = binding->getScope()->getSemantics()->getModule();

// TODO ensure more than 2 @ is an error for any real symbol
// TODO add type specialization here?
return fmt::format("{1}@@@{0}", module->uri(), binding->getSymbol()->getDisplay());
if (postFix.empty())
return fmt::format("{1}@@@{0}", module->uri(), binding->getSymbol()->getDisplay());
else
return fmt::format("{1}@@@{0}:::{2}", module->uri(), binding->getSymbol()->getDisplay(), postFix);
}

LlvmBackend::LlvmBackend(instance<Namespace> lisp)
Expand Down Expand Up @@ -131,10 +134,6 @@ LlvmBackendProvider::LlvmBackendProvider()
llvm::InitializeNativeTarget();
llvm::InitializeNativeTargetAsmPrinter();
llvm::InitializeNativeTargetAsmParser();

llvm::InitializeAllTargets();
llvm::InitializeAllTargetMCs();
llvm::InitializeAllAsmPrinters();
}

instance<> LlvmBackendProvider::init(instance<Namespace> ns) const
Expand Down
2 changes: 1 addition & 1 deletion src/backendllvm/LlvmBackend.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ namespace lisp
public:
using JitModule = decltype(_compileLayer)::ModuleHandleT;

CULTLANG_BACKENDLLVM_EXPORTED static std::string mangledName(instance<SBindable>);
CULTLANG_BACKENDLLVM_EXPORTED static std::string mangledName(instance<SBindable>, std::string const& postFix = "");

public:

Expand Down
243 changes: 198 additions & 45 deletions src/backendllvm/LlvmCompiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,15 @@ using namespace craft::lisp;
using namespace llvm;
using namespace llvm::orc;

CRAFT_DEFINE(SLlvmAbi)
{
_.defaults();
}

/******************************************************************************
** LlvmCompiler
******************************************************************************/

CRAFT_DEFINE(LlvmCompiler)
{
_.defaults();
Expand All @@ -23,8 +32,11 @@ LlvmCompiler::LlvmCompiler(instance<LlvmBackend> backend)
type_instanceMetaHeader = llvm::StructType::create(_backend->context, "!instancemetaheader");
type_instanceMetaHeader->setBody({ type_anyPtr, type_anyPtr, type_anyPtr, type_anyPtr });
type_anyInstance = llvm::StructType::get(_backend->context, { llvm::PointerType::get(type_instanceMetaHeader, 0), type_anyPtr });
}

state = new CompilerState();
void LlvmCompiler::craft_setupInstance()
{
_state = instance<LlvmCompileState>::make(craft_instance());
}

instance<LlvmBackend> LlvmCompiler::getBackend()
Expand All @@ -34,36 +46,7 @@ instance<LlvmBackend> LlvmCompiler::getBackend()

void LlvmCompiler::compile(instance<lisp::SCultSemanticNode> node)
{
try
{
auto res = _fn_system_compile.getFeature<PSubroutine>()->execute(_fn_system_compile, { craft_instance(), node });
}
catch (std::exception const& ex)
{
_backend->getNamespace()->getEnvironment()->log()->warn("Compiler does not support node `{1}`, default returned: {0}", ex.what(), node);
}
}

void LlvmCompiler::compile_setModule(instance<lisp::Module> module)
{
state->currentModule = module;
state->codeModule = module->require<LlvmModule>()->getIr().get();
}
void LlvmCompiler::compile_setFunction(instance<lisp::Function> func)
{
auto name = LlvmBackend::mangledName(func);

state->codeFunction = llvm::Function::Create(
getLlvmType(func->subroutine_signature()),
llvm::Function::ExternalLinkage,
name,
state->codeModule);

if (state->irBuilder != nullptr) delete state->irBuilder;
state->irBuilder = new llvm::IRBuilder<>(_backend->context);

auto block = llvm::BasicBlock::Create(_backend->context, name, state->codeFunction);
state->irBuilder->SetInsertPoint(block);
_state->compile(node);
}

LlvmCompiler::_TypeCacheEntry LlvmCompiler::_getTypeCache(types::TypeId type)
Expand Down Expand Up @@ -108,46 +91,216 @@ llvm::FunctionType* LlvmCompiler::getLlvmType(types::ExpressionStore signature)
if (!arrow->input->kind().isType<ExpressionTuple>()) throw stdext::exception("getLlvmType(): malformed expression (not tuple).");
auto tuple = (ExpressionTuple*)arrow->input;

// TODO windows ABI
args.push_back(llvm::PointerType::get(getLlvmType(arrow->output), 0));

for (auto arg : tuple->entries)
{
args.push_back(getLlvmType(arg));
}

return_ = getLlvmType(arrow->output);
//return_ = getLlvmType(arrow->output);
return_ = llvm::Type::getVoidTy(_backend->context);

auto ret = llvm::FunctionType::get(return_, args, false);

return ret;
}

void LlvmCompiler::builtin_validateSpecialForms(instance<lisp::Module> module)
{
_fn_system_compile = module->get<CultSemantics>()->lookup(Symbol::makeSymbol("compile"))->getSite()->valueAst();
}

/******************************************************************************
** LlvmCompileState
******************************************************************************/

CRAFT_DEFINE(LlvmCompileState)
{
_.defaults();
}

LlvmCompileState::LlvmCompileState(instance<LlvmCompiler> compiler)
{
_compiler = compiler;

context = &getCompiler()->getBackend()->context;
irBuilder = nullptr;
lastReturnedValue = nullptr;
codeModule = nullptr;
codeFunction = nullptr;
}

void LlvmCompileState::craft_setupInstance()
{
_abi = instance<LlvmAbiWindows>::make(craft_instance());
}

instance<LlvmCompiler> LlvmCompileState::getCompiler() const
{
return _compiler;
}

void LlvmCompileState::compile(instance<lisp::SCultSemanticNode> node)
{
auto _mm_compiler = _compiler->_fn_system_compile;

try
{
auto res = _mm_compiler.getFeature<PSubroutine>()->execute(_mm_compiler, { craft_instance(), _abi, node });
}
catch (std::exception const& ex)
{
getCompiler()->getBackend()
->getNamespace()->getEnvironment()
->log()->warn("Compiler does not support node `{1}`, default returned: {0}", ex.what(), node);
}
}

void LlvmCompileState::setModule(instance<lisp::Module> module)
{
currentModule = module;
codeModule = module->require<LlvmModule>()->getIr().get();
}
void LlvmCompileState::setFunction(instance<lisp::Function> func)
{
currentFunction = func;
auto name = LlvmBackend::mangledName(func, _abi->abiName());

codeFunction = llvm::Function::Create(
getCompiler()->getLlvmType(func->subroutine_signature()),
llvm::Function::ExternalLinkage,
name,
codeModule);

if (irBuilder != nullptr) delete irBuilder;
irBuilder = new llvm::IRBuilder<>(*context);

auto block = llvm::BasicBlock::Create(*context, name, codeFunction);
irBuilder->SetInsertPoint(block);

return llvm::FunctionType::get(return_, args, false);
_abi->doFunctionPre();
}

llvm::Value* LlvmCompiler::build_instanceAsConstant(instance<> inst)
llvm::Value* LlvmCompileState::genInstanceAsConstant(instance<> inst)
{
auto entry = _getTypeCache(inst.typeId());
auto entry = _compiler->_getTypeCache(inst.typeId());

return llvm::ConstantStruct::getAnon(
{
llvm::ConstantExpr::getIntToPtr(llvm::ConstantInt::get(llvm::Type::getInt64Ty(_backend->context), (uint64_t)inst.asInternalPointer()), llvm::PointerType::get(type_instanceMetaHeader, 0)),
llvm::ConstantExpr::getIntToPtr(llvm::ConstantInt::get(llvm::Type::getInt64Ty(_backend->context), (uint64_t)inst.get()), llvm::PointerType::get(entry.opaque_struct, 0))
llvm::ConstantExpr::getIntToPtr(
llvm::ConstantInt::get(
llvm::Type::getInt64Ty(*context),
(uint64_t)inst.asInternalPointer()),
llvm::PointerType::get(_compiler->type_instanceMetaHeader, 0)),
llvm::ConstantExpr::getIntToPtr(
llvm::ConstantInt::get(
llvm::Type::getInt64Ty(*context),
(uint64_t)inst.get()),
llvm::PointerType::get(entry.opaque_struct, 0))
});
}

llvm::Value* LlvmCompiler::build_instanceCast(llvm::Value* value, TypeId type)
llvm::Value* LlvmCompileState::genInstanceCast(llvm::Value* value, TypeId type)
{
_TypeCacheEntry* entry = nullptr;
if (type != types::None) entry = &_getTypeCache(type);
LlvmCompiler::_TypeCacheEntry* entry = nullptr;
if (type != types::None) entry = &_compiler->_getTypeCache(type);

auto const targetPtrType = (entry == nullptr) ? type_anyPtr : llvm::PointerType::get(entry->opaque_struct, 0);
auto const targetPtrType = (entry == nullptr) ? _compiler->type_anyPtr : llvm::PointerType::get(entry->opaque_struct, 0);

if (auto *vconst = dyn_cast<llvm::Constant>(value))
{
return llvm::ConstantStruct::getAnon(
{
llvm::ConstantExpr::getExtractValue(vconst, { 0 }),
llvm::ConstantExpr::getBitCast(llvm::ConstantExpr::getExtractValue(vconst, { 1 }), targetPtrType)
llvm::ConstantExpr::getExtractValue(vconst,{ 0 }),
llvm::ConstantExpr::getBitCast(llvm::ConstantExpr::getExtractValue(vconst,{ 1 }), targetPtrType)
});
}
else throw stdext::exception("Runtime casting not supported yet.");
}

void LlvmCompiler::builtin_validateSpecialForms(instance<lisp::Module> module)
void LlvmCompileState::genReturn(llvm::Value* v)
{
_fn_system_compile = module->get<CultSemantics>()->lookup(Symbol::makeSymbol("compile"))->getSite()->valueAst();
_abi->genReturn(v);
}

/******************************************************************************
** LlvmAbiBase
******************************************************************************/

CRAFT_DEFINE(LlvmAbiBase)
{
_.use<SLlvmAbi>().byCasting();

_.defaults();
}

LlvmAbiBase::LlvmAbiBase(instance<LlvmCompileState> compileState)
{
_c = compileState;
}

std::string LlvmAbiBase::abiName()
{
return "";
}

void LlvmAbiBase::doFunctionPre()
{

}
void LlvmAbiBase::doFunctionPost()
{

}

void LlvmAbiBase::genReturn(llvm::Value* v)
{
_c->irBuilder->CreateRet(v);
}

/******************************************************************************
** LlvmAbiWindows
******************************************************************************/

CRAFT_DEFINE(LlvmAbiWindows)
{
_.parent<LlvmAbiBase>();

_.defaults();
}

LlvmAbiWindows::LlvmAbiWindows(instance<LlvmCompileState> compileState)
: LlvmAbiBase(compileState)
{

}

std::string LlvmAbiWindows::abiName()
{
return "windows";
}

void LlvmAbiWindows::doFunctionPre()
{
_c->codeFunction->addAttribute(1, llvm::Attribute::StructRet);
}

void LlvmAbiWindows::genReturn(llvm::Value* v)
{
// Assert struct return

auto ret = _c->codeFunction->arg_begin() + 0;

if (auto *vconst = dyn_cast<llvm::Constant>(v))
{
_c->irBuilder->CreateStore(vconst, ret);
}
else
{
auto callee = llvm::Intrinsic::getDeclaration(_c->codeModule, llvm::Intrinsic::memcpy, {});
}

_c->irBuilder->CreateRetVoid();
}
Loading

0 comments on commit b2ba0d7

Please sign in to comment.