Commit 5a20e7d9 authored by Bednárek David RNDr. Ph.D.'s avatar Bednárek David RNDr. Ph.D.
Browse files

fmwk: current_function_return_type, create_basic_block, get_ir_int64

improved resilience against nullptr
parent d5683d08
...@@ -155,6 +155,8 @@ namespace cecko { ...@@ -155,6 +155,8 @@ namespace cecko {
CKTypedefConstSafeObs CKContext::define_typedef(const std::string& name, const CKTypeRefPack& type_pack, loc_t loc) CKTypedefConstSafeObs CKContext::define_typedef(const std::string& name, const CKTypeRefPack& type_pack, loc_t loc)
{ {
if (!type_pack.type)
return nullptr;
if (!!conflicting_idf(name)) if (!!conflicting_idf(name))
{ {
get_ctx()->message(errors::DUPLICATE_IDF, loc, name); get_ctx()->message(errors::DUPLICATE_IDF, loc, name);
...@@ -170,6 +172,8 @@ namespace cecko { ...@@ -170,6 +172,8 @@ namespace cecko {
} }
CKConstantConstSafeObs CKContext::define_constant(const std::string& name, CKIRConstantIntObs value, loc_t loc) CKConstantConstSafeObs CKContext::define_constant(const std::string& name, CKIRConstantIntObs value, loc_t loc)
{ {
if (!value)
return nullptr;
if (!!conflicting_idf(name)) if (!!conflicting_idf(name))
{ {
get_ctx()->message(errors::DUPLICATE_IDF, loc, name); get_ctx()->message(errors::DUPLICATE_IDF, loc, name);
...@@ -185,6 +189,8 @@ namespace cecko { ...@@ -185,6 +189,8 @@ namespace cecko {
} }
void CKContext::define_var(const std::string& name, const CKTypeRefPack& type_pack, loc_t loc) void CKContext::define_var(const std::string& name, const CKTypeRefPack& type_pack, loc_t loc)
{ {
if (!type_pack.type)
return;
if (type_pack.type->is_void() || type_pack.type->is_function()) if (type_pack.type->is_void() || type_pack.type->is_function())
{ {
get_ctx()->message(errors::INVALID_VARIABLE_TYPE, loc); get_ctx()->message(errors::INVALID_VARIABLE_TYPE, loc);
...@@ -207,6 +213,9 @@ namespace cecko { ...@@ -207,6 +213,9 @@ namespace cecko {
CKFunctionSafeObs CKContext::declare_function(const CIName& n, CKTypeObs type, loc_t loc) CKFunctionSafeObs CKContext::declare_function(const CIName& n, CKTypeObs type, loc_t loc)
{ {
if (!type)
return nullptr;
if (!type->is_function()) if (!type->is_function())
{ {
get_ctx()->message(errors::INVALID_FUNCTION_TYPE, loc); get_ctx()->message(errors::INVALID_FUNCTION_TYPE, loc);
...@@ -223,16 +232,28 @@ namespace cecko { ...@@ -223,16 +232,28 @@ namespace cecko {
void CKContext::enter_function(CKFunctionObs f, CKFunctionFormalPackArray pack, loc_t loc) void CKContext::enter_function(CKFunctionObs f, CKFunctionFormalPackArray pack, loc_t loc)
{ {
if (f->is_defined()) if (!!f && f->is_defined())
{ {
get_ctx()->message(errors::DUPLICATE_FUNCTION_DEFINITION, loc, f->get_name()); get_ctx()->message(errors::DUPLICATE_FUNCTION_DEFINITION, loc, f->get_name());
} }
assert(!loctable_); assert(!loctable_);
current_function_ = f;
if (!!f)
current_function_ir_ = f->get_function_ir();
else
current_function_ir_ = CKCreateFunction(CKGetFunctionType(CKGetVoidType(builder_.getContext()), CKIRTypeObsArray(),false), "__dummy", module_);
// FUNCTION PROLOG // FUNCTION PROLOG
auto BB0 = CKCreateBasicBlock("prolog", f->get_function_ir()); auto BB0 = CKCreateBasicBlock("prolog", current_function_ir_);
alloca_builder_.SetInsertPoint(BB0); alloca_builder_.SetInsertPoint(BB0);
loctable_ = f->define(globtable_, alloca_builder_, std::move(pack)); if (!!f)
start_bb_ = CKCreateBasicBlock("start", f->get_function_ir()); loctable_ = f->define(globtable_, alloca_builder_, std::move(pack));
else
{
if ( ! dummy_loctable_ )
dummy_loctable_ = std::make_unique<CKLocalTable>(globtable_);
loctable_ = &*dummy_loctable_;
}
start_bb_ = CKCreateBasicBlock("start", current_function_ir_);
builder_.SetInsertPoint(start_bb_); builder_.SetInsertPoint(start_bb_);
} }
......
...@@ -170,17 +170,23 @@ namespace cecko { ...@@ -170,17 +170,23 @@ namespace cecko {
{ {
return llvm::Function::Create(FT, llvm::Function::ExternalLinkage, name, M); return llvm::Function::Create(FT, llvm::Function::ExternalLinkage, name, M);
} }
/// @endcond
/// Create a new basic block /// Create a new basic block
inline CKIRBasicBlockObs CKCreateBasicBlock(const std::string& name, CKIRFunctionObs F) inline CKIRBasicBlockObs CKCreateBasicBlock(const std::string& name, CKIRFunctionObs F)
{ {
if (!F)
return nullptr;
return llvm::BasicBlock::Create(F->getContext(), name, F); return llvm::BasicBlock::Create(F->getContext(), name, F);
} }
/// @endcond
/// Get integral constant from a llvm::Value /// Get integral constant from a llvm::Value
inline CKIRConstantIntObs CKTryGetConstantInt(CKIRValueObs v) inline CKIRConstantIntObs CKTryGetConstantInt(CKIRValueObs v)
{ {
if (!v)
return nullptr;
if (!llvm::isa< llvm::ConstantInt>(v))
return nullptr;
return llvm::cast<llvm::ConstantInt>(v); return llvm::cast<llvm::ConstantInt>(v);
} }
......
...@@ -53,6 +53,8 @@ namespace cecko { ...@@ -53,6 +53,8 @@ namespace cecko {
unsigned int idx = 0; unsigned int idx = 0;
for (auto&& a : items) for (auto&& a : items)
{ {
if (!a.pack.type)
continue;
elements_ir.push_back(a.pack.type->get_ir()); elements_ir.push_back(a.pack.type->get_ir());
auto p = elements_.try_emplace(a.name, a.pack, idx, a.loc); auto p = elements_.try_emplace(a.name, a.pack, idx, a.loc);
elements_ordered_.push_back(p); elements_ordered_.push_back(p);
...@@ -106,7 +108,10 @@ namespace cecko { ...@@ -106,7 +108,10 @@ namespace cecko {
: ret_type_(ret_type), arg_types_(std::move(arg_types)), variadic_(variadic), irt_(nullptr) : ret_type_(ret_type), arg_types_(std::move(arg_types)), variadic_(variadic), irt_(nullptr)
{ {
CKIRTypeObsArray arg_ir_types(arg_types_.size()); CKIRTypeObsArray arg_ir_types(arg_types_.size());
std::transform(arg_types_.begin(), arg_types_.end(), arg_ir_types.begin(), [](auto&& a) { return a->get_ir(); }); std::transform(arg_types_.begin(), arg_types_.end(), arg_ir_types.begin(),
[](auto&& a) {
return a->get_ir();
});
irt_ = CKGetFunctionType(ret_type_->get_ir(), std::move(arg_ir_types), variadic_); irt_ = CKGetFunctionType(ret_type_->get_ir(), std::move(arg_ir_types), variadic_);
} }
...@@ -430,12 +435,24 @@ namespace cecko { ...@@ -430,12 +435,24 @@ namespace cecko {
CKLocalTableObs CKFunction::define(CKAbstractScopeObs parent, CKIRBuilderRef builder, CKFunctionFormalPackArray formal_packs) CKLocalTableObs CKFunction::define(CKAbstractScopeObs parent, CKIRBuilderRef builder, CKFunctionFormalPackArray formal_packs)
{ {
assert(!loctab_); assert(!loctab_);
assert(type_->get_function_arg_count() == formal_packs.size());
loctab_ = std::make_unique<CKLocalTable>(parent); loctab_ = std::make_unique<CKLocalTable>(parent);
formal_packs_ = std::move(formal_packs); formal_packs_ = std::move(formal_packs);
loctab_->varsFromArgs(builder, this, formal_packs_); loctab_->varsFromArgs(builder, this, formal_packs_);
return &*loctab_; return &*loctab_;
} }
CKTypeSafeObs CKContext::current_function_return_type()
{
assert(!!loctable_);
if (!current_function_)
return nullptr;
auto ft = current_function_->get_function_type();
if (!ft)
return nullptr;
return ft->get_function_return_type();
}
void CKFunction::dump(CIOStream& os) const void CKFunction::dump(CIOStream& os) const
{ {
auto f_type = get_function_type(); auto f_type = get_function_type();
...@@ -503,6 +520,8 @@ namespace cecko { ...@@ -503,6 +520,8 @@ namespace cecko {
globtable_(tab->globtable()), globtable_(tab->globtable()),
loctable_(nullptr), loctable_(nullptr),
module_(tab->module()), module_(tab->module()),
current_function_(nullptr),
current_function_ir_(nullptr),
alloca_builder_(tab->module()->getContext()), alloca_builder_(tab->module()->getContext()),
builder_(tab->module()->getContext()), builder_(tab->module()->getContext()),
start_bb_(nullptr), start_bb_(nullptr),
...@@ -574,11 +593,15 @@ namespace cecko { ...@@ -574,11 +593,15 @@ namespace cecko {
void CKContext::define_struct_type_close(CKStructTypeObs type, const CKStructItemArray& items) void CKContext::define_struct_type_close(CKStructTypeObs type, const CKStructItemArray& items)
{ {
if (!type)
return;
type->finalize(items); type->finalize(items);
} }
void CKContext::define_enum_type_close(CKEnumTypeObs type, CKConstantObsVector items) void CKContext::define_enum_type_close(CKEnumTypeObs type, CKConstantObsVector items)
{ {
if (!type)
return;
type->finalize(std::move(items)); type->finalize(std::move(items));
} }
...@@ -630,14 +653,14 @@ namespace cecko { ...@@ -630,14 +653,14 @@ namespace cecko {
CKFunctionTypeSafeObs CKContext::get_function_type(CKTypeObs ret_type, CKTypeObsArray arg_types, bool variadic) CKFunctionTypeSafeObs CKContext::get_function_type(CKTypeObs ret_type, CKTypeObsArray arg_types, bool variadic)
{ {
if (ret_type->is_array() || ret_type->is_function()) if (!ret_type || ret_type->is_array() || ret_type->is_function())
{ {
// cannot return array/function // cannot return array/function
return nullptr; return nullptr;
} }
for (auto&& a : arg_types) for (auto&& a : arg_types)
{ {
if (a->is_void() || a->is_array() || a->is_function()) if (!a || a->is_void() || a->is_array() || a->is_function())
{ {
// cannot pass void/array/function // cannot pass void/array/function
// note: Cecko does not support implicit array/function-to-pointer conversion on argument declarations // note: Cecko does not support implicit array/function-to-pointer conversion on argument declarations
......
...@@ -1111,6 +1111,8 @@ namespace cecko { ...@@ -1111,6 +1111,8 @@ namespace cecko {
void enter_block(); void enter_block();
/// Signalize exiting of a compound statement other than a function definition /// Signalize exiting of a compound statement other than a function definition
void exit_block(); void exit_block();
/// The return type of the current function
CKTypeSafeObs current_function_return_type();
/// @} /// @}
/// @name Built-in types /// @name Built-in types
...@@ -1204,9 +1206,19 @@ namespace cecko { ...@@ -1204,9 +1206,19 @@ namespace cecko {
bool is_typedef(const CIName& n) const; bool is_typedef(const CIName& n) const;
/// @} /// @}
/// @name Representation of integer constants /// @name Direct access to LLVM types
/// @{ /// @{
/// LLVM representation of C-types "int64_t" and "uint64_t"
CKIRTypeObs get_ir_int64()
{
return llvm::Type::getInt64Ty(builder_.getContext());
}
/// @}
/// @name Representation of integer constants
/// @{
/// LLVM constant of type "char" /// LLVM constant of type "char"
CKIRConstantIntObs get_int8_constant(std::int_fast32_t v) CKIRConstantIntObs get_int8_constant(std::int_fast32_t v)
{ {
...@@ -1220,9 +1232,21 @@ namespace cecko { ...@@ -1220,9 +1232,21 @@ namespace cecko {
} }
/// @} /// @}
/// @name Active code builder /// @name Basic blocks
/// @{ /// @{
/// Create a new basic block in the current function
CKIRBasicBlockObs create_basic_block(const std::string & name)
{
if (!current_function_ir_)
return nullptr;
return CKCreateBasicBlock(name, current_function_ir_);
}
/// @}
/// @name Active code builder
/// @{
/// The active builder for the currently open basic block (or inactive) /// The active builder for the currently open basic block (or inactive)
CKIRBuilderObs builder() CKIRBuilderObs builder()
{ {
...@@ -1256,7 +1280,10 @@ namespace cecko { ...@@ -1256,7 +1280,10 @@ namespace cecko {
CKGlobalTableObs globtable_; CKGlobalTableObs globtable_;
CKIRModuleObs module_; CKIRModuleObs module_;
CKLocalTableObs loctable_; CKLocalTableObs loctable_;
std::unique_ptr<CKLocalTable> dummy_loctable_;
CKFunctionObs current_function_;
CKIRFunctionObs current_function_ir_;
CKIRBuilder alloca_builder_; CKIRBuilder alloca_builder_;
CKIRBuilder builder_; CKIRBuilder builder_;
CKIRBasicBlockObs start_bb_; CKIRBasicBlockObs start_bb_;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment