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 {
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))
{
get_ctx()->message(errors::DUPLICATE_IDF, loc, name);
......@@ -170,6 +172,8 @@ namespace cecko {
}
CKConstantConstSafeObs CKContext::define_constant(const std::string& name, CKIRConstantIntObs value, loc_t loc)
{
if (!value)
return nullptr;
if (!!conflicting_idf(name))
{
get_ctx()->message(errors::DUPLICATE_IDF, loc, name);
......@@ -185,6 +189,8 @@ namespace cecko {
}
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())
{
get_ctx()->message(errors::INVALID_VARIABLE_TYPE, loc);
......@@ -207,6 +213,9 @@ namespace cecko {
CKFunctionSafeObs CKContext::declare_function(const CIName& n, CKTypeObs type, loc_t loc)
{
if (!type)
return nullptr;
if (!type->is_function())
{
get_ctx()->message(errors::INVALID_FUNCTION_TYPE, loc);
......@@ -223,16 +232,28 @@ namespace cecko {
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());
}
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
auto BB0 = CKCreateBasicBlock("prolog", f->get_function_ir());
auto BB0 = CKCreateBasicBlock("prolog", current_function_ir_);
alloca_builder_.SetInsertPoint(BB0);
loctable_ = f->define(globtable_, alloca_builder_, std::move(pack));
start_bb_ = CKCreateBasicBlock("start", f->get_function_ir());
if (!!f)
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_);
}
......
......@@ -170,17 +170,23 @@ namespace cecko {
{
return llvm::Function::Create(FT, llvm::Function::ExternalLinkage, name, M);
}
/// @endcond
/// Create a new basic block
inline CKIRBasicBlockObs CKCreateBasicBlock(const std::string& name, CKIRFunctionObs F)
{
if (!F)
return nullptr;
return llvm::BasicBlock::Create(F->getContext(), name, F);
}
/// @endcond
/// Get integral constant from a llvm::Value
inline CKIRConstantIntObs CKTryGetConstantInt(CKIRValueObs v)
{
if (!v)
return nullptr;
if (!llvm::isa< llvm::ConstantInt>(v))
return nullptr;
return llvm::cast<llvm::ConstantInt>(v);
}
......
......@@ -53,6 +53,8 @@ namespace cecko {
unsigned int idx = 0;
for (auto&& a : items)
{
if (!a.pack.type)
continue;
elements_ir.push_back(a.pack.type->get_ir());
auto p = elements_.try_emplace(a.name, a.pack, idx, a.loc);
elements_ordered_.push_back(p);
......@@ -106,7 +108,10 @@ namespace cecko {
: ret_type_(ret_type), arg_types_(std::move(arg_types)), variadic_(variadic), irt_(nullptr)
{
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_);
}
......@@ -430,12 +435,24 @@ namespace cecko {
CKLocalTableObs CKFunction::define(CKAbstractScopeObs parent, CKIRBuilderRef builder, CKFunctionFormalPackArray formal_packs)
{
assert(!loctab_);
assert(type_->get_function_arg_count() == formal_packs.size());
loctab_ = std::make_unique<CKLocalTable>(parent);
formal_packs_ = std::move(formal_packs);
loctab_->varsFromArgs(builder, this, formal_packs_);
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
{
auto f_type = get_function_type();
......@@ -503,6 +520,8 @@ namespace cecko {
globtable_(tab->globtable()),
loctable_(nullptr),
module_(tab->module()),
current_function_(nullptr),
current_function_ir_(nullptr),
alloca_builder_(tab->module()->getContext()),
builder_(tab->module()->getContext()),
start_bb_(nullptr),
......@@ -574,11 +593,15 @@ namespace cecko {
void CKContext::define_struct_type_close(CKStructTypeObs type, const CKStructItemArray& items)
{
if (!type)
return;
type->finalize(items);
}
void CKContext::define_enum_type_close(CKEnumTypeObs type, CKConstantObsVector items)
{
if (!type)
return;
type->finalize(std::move(items));
}
......@@ -630,14 +653,14 @@ namespace cecko {
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
return nullptr;
}
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
// note: Cecko does not support implicit array/function-to-pointer conversion on argument declarations
......
......@@ -1111,6 +1111,8 @@ namespace cecko {
void enter_block();
/// Signalize exiting of a compound statement other than a function definition
void exit_block();
/// The return type of the current function
CKTypeSafeObs current_function_return_type();
/// @}
/// @name Built-in types
......@@ -1204,9 +1206,19 @@ namespace cecko {
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"
CKIRConstantIntObs get_int8_constant(std::int_fast32_t v)
{
......@@ -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)
CKIRBuilderObs builder()
{
......@@ -1256,7 +1280,10 @@ namespace cecko {
CKGlobalTableObs globtable_;
CKIRModuleObs module_;
CKLocalTableObs loctable_;
std::unique_ptr<CKLocalTable> dummy_loctable_;
CKFunctionObs current_function_;
CKIRFunctionObs current_function_ir_;
CKIRBuilder alloca_builder_;
CKIRBuilder builder_;
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