Skip to content
22 changes: 19 additions & 3 deletions include/IRDec/DITypeLifter.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#define GLU_IR_DEC_DI_TYPE_LIFTER_HPP

#include "AST/ASTContext.hpp"
#include "AST/Decls.hpp"
#include "AST/Types.hpp"
#include <llvm/IR/DebugInfoMetadata.h>

Expand All @@ -10,6 +11,7 @@ namespace glu::irdec {
class DITypeLifter {

glu::ast::ASTContext &_context;
llvm::DenseMap<llvm::DIType const *, glu::ast::DeclBase *> _declBindings;

public:
DITypeLifter(glu::ast::ASTContext &context) : _context(context) { }
Expand All @@ -18,7 +20,7 @@ class DITypeLifter {
/// @brief Lift a DIType to a GLU type
/// @param diType The DIType to lift
/// @return The lifted GLU type, or nullptr if the type could not be lifted
glu::types::TypeBase *lift(llvm::DIType const *diType) const;
glu::types::TypeBase *lift(llvm::DIType const *diType);

/// @brief Handle a DIBasicType and lift it to a GLU type
/// @param arena The memory arena to use for allocation
Expand All @@ -33,15 +35,29 @@ class DITypeLifter {
/// @param diCompositeType The DICompositeType to handle
/// @return The lifted GLU type, or nullptr if the type could not be lifted
glu::types::TypeBase *
handleComposedTypes(llvm::DICompositeType const *diCompositeType) const;
handleComposedTypes(llvm::DICompositeType const *diCompositeType);

/// @brief Handle a DIDerivedType and lift it to a GLU type
/// @param typesArena The memory arena to use for type allocation
/// @param astArena The memory arena to use for AST allocation
/// @param diDerivedType The DIDerivedType to handle
/// @return The lifted GLU type, or nullptr if the type could not be lifted
glu::types::TypeBase *
handleDerivedType(llvm::DIDerivedType const *diDerivedType) const;
handleDerivedType(llvm::DIDerivedType const *diDerivedType);

/// @brief Handle a DISubroutineType and lift it to a GLU type
/// @param diSubroutineType The DISubroutineType to handle
/// @return The lifted GLU type, or nullptr if the type could not be lifted
glu::types::TypeBase *
handleSubroutineType(llvm::DISubroutineType const *diSubroutineType);

/// @brief Get the declaration bindings map
/// @return The declaration bindings map
llvm::DenseMap<llvm::DIType const *, glu::ast::DeclBase *> &
getDeclBindings()
{
return _declBindings;
}
};

} // namespace glu::irdec
Expand Down
7 changes: 3 additions & 4 deletions include/IRDec/ModuleLifter.hpp
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
#ifndef GLU_IRDEC_MODULE_LIFTER_HPP
#define GLU_IRDEC_MODULE_LIFTER_HPP

#include "AST/Decls.hpp"
#include "GIL/Module.hpp"
#include <llvm/IR/Module.h>

namespace glu::irdec {

glu::gil::Module *liftModule(
glu::ast::ASTContext &astContext, llvm::BumpPtrAllocator &arena,
llvm::Module *llvmModule
);
glu::ast::ModuleDecl *
liftModule(glu::ast::ASTContext &astContext, llvm::Module *llvmModule);

} // namespace glu::irdec

Expand Down
67 changes: 59 additions & 8 deletions lib/IRDec/DITypeLifter.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#include "DITypeLifter.hpp"
#include "AST/Decls.hpp"
#include <llvm/BinaryFormat/Dwarf.h>

namespace glu::irdec {
Expand Down Expand Up @@ -27,9 +26,8 @@ DITypeLifter::handleBasicType(llvm::DIBasicType const *diBasicType) const
}
}

glu::types::TypeBase *DITypeLifter::handleComposedTypes(
llvm::DICompositeType const *diCompositeType
) const
glu::types::TypeBase *
DITypeLifter::handleComposedTypes(llvm::DICompositeType const *diCompositeType)
{
using namespace glu::types;

Expand All @@ -38,6 +36,14 @@ glu::types::TypeBase *DITypeLifter::handleComposedTypes(
auto tag = diCompositeType->getTag();
switch (tag) {
case llvm::dwarf::DW_TAG_structure_type: {
if (auto it = _declBindings.find(diCompositeType);
it != _declBindings.end()) {
if (auto *structDecl
= llvm::dyn_cast<ast::StructDecl>(it->second)) {
return typesArena.create<StructTy>(structDecl);
}
}

std::vector<ast::FieldDecl *> fieldDecls;
if (auto elements = diCompositeType->getElements()) {
for (auto *elem : elements) {
Expand Down Expand Up @@ -65,6 +71,7 @@ glu::types::TypeBase *DITypeLifter::handleComposedTypes(
),
fieldDecls
);
_declBindings[diCompositeType] = structDecl;
return typesArena.create<StructTy>(structDecl);
}
case llvm::dwarf::DW_TAG_array_type: {
Expand Down Expand Up @@ -95,6 +102,12 @@ glu::types::TypeBase *DITypeLifter::handleComposedTypes(
return nullptr;
}
case llvm::dwarf::DW_TAG_enumeration_type: {
if (auto it = _declBindings.find(diCompositeType);
it != _declBindings.end()) {
if (auto *enumDecl = llvm::dyn_cast<ast::EnumDecl>(it->second)) {
return typesArena.create<EnumTy>(enumDecl);
}
}
std::vector<ast::FieldDecl *> enumerators;
if (auto elements = diCompositeType->getElements()) {
for (auto *elem : elements) {
Expand All @@ -115,14 +128,15 @@ glu::types::TypeBase *DITypeLifter::handleComposedTypes(
),
enumerators
);
_declBindings[diCompositeType] = enumDecl;
return typesArena.create<EnumTy>(enumDecl);
}
default: return nullptr;
}
}

glu::types::TypeBase *
DITypeLifter::handleDerivedType(llvm::DIDerivedType const *diDerivedType) const
DITypeLifter::handleDerivedType(llvm::DIDerivedType const *diDerivedType)
{
using namespace glu::types;

Expand All @@ -148,7 +162,43 @@ DITypeLifter::handleDerivedType(llvm::DIDerivedType const *diDerivedType) const
}
}

glu::types::TypeBase *DITypeLifter::lift(llvm::DIType const *diType) const
glu::types::TypeBase *DITypeLifter::handleSubroutineType(
llvm::DISubroutineType const *diSubroutineType
)
{
using namespace glu::types;

auto &typesArena = _context.getTypesMemoryArena();
auto types = diSubroutineType->getTypeArray();

if (types.size() == 0) {
return nullptr;
}

// First element is return type
auto *returnType = lift(llvm::cast<llvm::DIType>(types[0]));
if (!returnType) {
return nullptr;
}

// Remaining elements are parameter types
llvm::SmallVector<TypeBase *, 4> paramTypes;
for (size_t i = 1; i < types.size(); ++i) {
if (auto *diType = llvm::dyn_cast_if_present<llvm::DIType>(types[i])) {
auto *paramType = lift(diType);
if (!paramType) {
return nullptr;
}
paramTypes.push_back(paramType);
}
}

return FunctionTy::create(
typesArena.getAllocator(), paramTypes, returnType, false
);
}

glu::types::TypeBase *DITypeLifter::lift(llvm::DIType const *diType)
{
if (!diType) {
return nullptr;
Expand All @@ -158,9 +208,10 @@ glu::types::TypeBase *DITypeLifter::lift(llvm::DIType const *diType) const
return handleBasicType(llvm::cast<llvm::DIBasicType>(diType));
case llvm::Metadata::MetadataKind::DICompositeTypeKind:
return handleComposedTypes(llvm::cast<llvm::DICompositeType>(diType));
case llvm::Metadata::MetadataKind::DIDerivedTypeKind: {
case llvm::Metadata::MetadataKind::DIDerivedTypeKind:
return handleDerivedType(llvm::cast<llvm::DIDerivedType>(diType));
}
case llvm::Metadata::MetadataKind::DISubroutineTypeKind:
return handleSubroutineType(llvm::cast<llvm::DISubroutineType>(diType));
default: return nullptr;
}
}
Expand Down
71 changes: 50 additions & 21 deletions lib/IRDec/ModuleLifter.cpp
Original file line number Diff line number Diff line change
@@ -1,54 +1,83 @@
#include "ModuleLifter.hpp"
#include "DITypeLifter.hpp"
#include "GILGen/GILGen.hpp"
#include "TypeLifter.hpp"
#include "llvm/IR/Function.h"

namespace glu::irdec {

class ModuleLifter {
glu::ast::ASTContext &_astContext;
glu::gilgen::GlobalContext _globalCtx;
llvm::Module *_llvmModule;

llvm::SmallVector<glu::ast::ParamDecl *, 4>
generateParamsDecls(llvm::ArrayRef<glu::types::TypeBase *> types)
{
llvm::SmallVector<glu::ast::ParamDecl *, 4> params;

for (size_t i = 0; i < types.size(); ++i) {
auto paramDecl
= _astContext.getASTMemoryArena().create<glu::ast::ParamDecl>(
SourceLocation::invalid,
copyString(
"param" + std::to_string(i),
_astContext.getASTMemoryArena().getAllocator()
),
types[i], nullptr
);
params.push_back(paramDecl);
}
return params;
}

public:
ModuleLifter(
glu::ast::ASTContext &astContext, llvm::BumpPtrAllocator &arena,
llvm::Module *llvmModule
)
: _astContext(astContext)
, _globalCtx(new(arena) glu::gil::Module(llvmModule->getName()), arena)
, _llvmModule(llvmModule)
ModuleLifter(glu::ast::ASTContext &astContext, llvm::Module *llvmModule)
: _astContext(astContext), _llvmModule(llvmModule)
{
}

~ModuleLifter() = default;

glu::gil::Module *detectExternalFunctions()
glu::ast::ModuleDecl *detectExternalFunctions()
{
TypeLifter typeLifter(_astContext);
DITypeLifter typeLifter(_astContext);
std::vector<glu::ast::DeclBase *> decls;

for (auto &func : _llvmModule->functions()) {
if (!func.isDeclaration()
&& func.getLinkage() == llvm::Function::ExternalLinkage) {
auto type = typeLifter.lift(func.getFunctionType());
auto subProgram = func.getSubprogram();
if (!subProgram)
continue;
auto type = typeLifter.lift(subProgram->getType());
if (auto funcType
= llvm::dyn_cast_if_present<glu::types::FunctionTy>(type)) {
glu::gil::Function *gilFunc = new (_globalCtx.arena)
glu::gil::Function(func.getName(), funcType, nullptr);
_globalCtx.module->addFunction(gilFunc);
auto funcDecl
= _astContext.getASTMemoryArena()
.create<glu::ast::FunctionDecl>(
SourceLocation::invalid, nullptr,
func.getName(), funcType,
generateParamsDecls(funcType->getParameters()
),
nullptr, glu::ast::Visibility::Public
);
decls.push_back(funcDecl);
}
}
}
return _globalCtx.module;

for (auto decl : typeLifter.getDeclBindings()) {
decls.push_back(decl.second);
}
return _astContext.getASTMemoryArena().create<glu::ast::ModuleDecl>(
SourceLocation::invalid, std::move(decls), &_astContext
);
}
};

glu::gil::Module *liftModule(
glu::ast::ASTContext &astContext, llvm::BumpPtrAllocator &arena,
llvm::Module *llvmModule
)
glu::ast::ModuleDecl *
liftModule(glu::ast::ASTContext &astContext, llvm::Module *llvmModule)
{
ModuleLifter lifter(astContext, arena, llvmModule);
ModuleLifter lifter(astContext, llvmModule);
return lifter.detectExternalFunctions();
}

Expand Down
Loading
Loading