Skip to content

Commit 30591a1

Browse files
committed
Refactor: LLVM: Define and use compute_fmt_specifier_and_arg()
1 parent e642072 commit 30591a1

File tree

1 file changed

+166
-164
lines changed

1 file changed

+166
-164
lines changed

src/libasr/codegen/asr_to_llvm.cpp

Lines changed: 166 additions & 164 deletions
Original file line numberDiff line numberDiff line change
@@ -7207,6 +7207,171 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor<ASRToLLVMVisitor>
72077207
handle_print(x);
72087208
}
72097209

7210+
// It appends the format specifier and arg based on the type of expression
7211+
void compute_fmt_specifier_and_arg(std::vector<std::string> &fmt,
7212+
std::vector<llvm::Value *> &args, ASR::expr_t *v, const Location &loc) {
7213+
int64_t ptr_loads_copy = ptr_loads;
7214+
int reduce_loads = 0;
7215+
ptr_loads = 2;
7216+
if( ASR::is_a<ASR::Var_t>(*v) ) {
7217+
ASR::Variable_t* var = ASRUtils::EXPR2VAR(v);
7218+
reduce_loads = var->m_intent == ASRUtils::intent_in;
7219+
if( ASR::is_a<ASR::Pointer_t>(*var->m_type) ) {
7220+
ptr_loads = 1;
7221+
}
7222+
}
7223+
ptr_loads = ptr_loads - reduce_loads;
7224+
lookup_enum_value_for_nonints = true;
7225+
this->visit_expr_wrapper(v, true);
7226+
lookup_enum_value_for_nonints = false;
7227+
ptr_loads = ptr_loads_copy;
7228+
ASR::ttype_t *t = ASRUtils::type_get_past_allocatable(ASRUtils::expr_type(v));
7229+
if( ASR::is_a<ASR::Const_t>(*t) ) {
7230+
t = ASRUtils::get_contained_type(t);
7231+
}
7232+
int a_kind = ASRUtils::extract_kind_from_ttype_t(t);
7233+
if( ASR::is_a<ASR::Pointer_t>(*t) && ASR::is_a<ASR::Var_t>(*v) ) {
7234+
if( ASRUtils::is_array(ASRUtils::type_get_past_pointer(t)) ) {
7235+
tmp = CreateLoad(arr_descr->get_pointer_to_data(tmp));
7236+
}
7237+
fmt.push_back("%lld");
7238+
llvm::Value* d = builder->CreatePtrToInt(tmp, getIntType(8, false));
7239+
args.push_back(d);
7240+
} else if (t->type == ASR::ttypeType::CPtr ||
7241+
(t->type == ASR::ttypeType::Pointer &&
7242+
(ASR::is_a<ASR::Var_t>(*v) || ASR::is_a<ASR::GetPointer_t>(*v)))
7243+
) {
7244+
fmt.push_back("%lld");
7245+
llvm::Value* d = builder->CreatePtrToInt(tmp, getIntType(8, false));
7246+
args.push_back(d);
7247+
} else if (ASRUtils::is_integer(*t)) {
7248+
switch( a_kind ) {
7249+
case 1 : {
7250+
fmt.push_back("%hhi");
7251+
break;
7252+
}
7253+
case 2 : {
7254+
fmt.push_back("%hi");
7255+
break;
7256+
}
7257+
case 4 : {
7258+
fmt.push_back("%d");
7259+
break;
7260+
}
7261+
case 8 : {
7262+
fmt.push_back("%lld");
7263+
break;
7264+
}
7265+
default: {
7266+
throw CodeGenError(R"""(Printing support is available only
7267+
for 8, 16, 32, and 64 bit integer kinds.)""",
7268+
loc);
7269+
}
7270+
}
7271+
args.push_back(tmp);
7272+
} else if (ASRUtils::is_unsigned_integer(*t)) {
7273+
switch( a_kind ) {
7274+
case 1 : {
7275+
fmt.push_back("%hhu");
7276+
break;
7277+
}
7278+
case 2 : {
7279+
fmt.push_back("%hu");
7280+
break;
7281+
}
7282+
case 4 : {
7283+
fmt.push_back("%u");
7284+
break;
7285+
}
7286+
case 8 : {
7287+
fmt.push_back("%llu");
7288+
break;
7289+
}
7290+
default: {
7291+
throw CodeGenError(R"""(Printing support is available only
7292+
for 8, 16, 32, and 64 bit unsigned integer kinds.)""",
7293+
loc);
7294+
}
7295+
}
7296+
args.push_back(tmp);
7297+
} else if (ASRUtils::is_real(*t)) {
7298+
llvm::Value *d;
7299+
switch( a_kind ) {
7300+
case 4 : {
7301+
// Cast float to double as a workaround for the fact that
7302+
// vprintf() seems to cast to double even for %f, which
7303+
// causes it to print 0.000000.
7304+
fmt.push_back("%13.8e");
7305+
d = builder->CreateFPExt(tmp,
7306+
llvm::Type::getDoubleTy(context));
7307+
break;
7308+
}
7309+
case 8 : {
7310+
fmt.push_back("%23.17e");
7311+
d = builder->CreateFPExt(tmp,
7312+
llvm::Type::getDoubleTy(context));
7313+
break;
7314+
}
7315+
default: {
7316+
throw CodeGenError(R"""(Printing support is available only
7317+
for 32, and 64 bit real kinds.)""",
7318+
loc);
7319+
}
7320+
}
7321+
args.push_back(d);
7322+
} else if (t->type == ASR::ttypeType::Character) {
7323+
fmt.push_back("%s");
7324+
args.push_back(tmp);
7325+
} else if (ASRUtils::is_logical(*t)) {
7326+
llvm::Value *cmp = builder->CreateICmpEQ(tmp, builder->getInt1(0));
7327+
llvm::Value *zero_str = builder->CreateGlobalStringPtr("False");
7328+
llvm::Value *one_str = builder->CreateGlobalStringPtr("True");
7329+
llvm::Value *str = builder->CreateSelect(cmp, zero_str, one_str);
7330+
fmt.push_back("%s");
7331+
args.push_back(str);
7332+
} else if (ASRUtils::is_complex(*t)) {
7333+
llvm::Type *type, *complex_type;
7334+
switch( a_kind ) {
7335+
case 4 : {
7336+
// Cast float to double as a workaround for the fact that
7337+
// vprintf() seems to cast to double even for %f, which
7338+
// causes it to print 0.000000.
7339+
fmt.push_back("(%f,%f)");
7340+
type = llvm::Type::getDoubleTy(context);
7341+
complex_type = complex_type_4;
7342+
break;
7343+
}
7344+
case 8 : {
7345+
fmt.push_back("(%lf,%lf)");
7346+
type = llvm::Type::getDoubleTy(context);
7347+
complex_type = complex_type_8;
7348+
break;
7349+
}
7350+
default: {
7351+
throw CodeGenError(R"""(Printing support is available only
7352+
for 32, and 64 bit complex kinds.)""",
7353+
loc);
7354+
}
7355+
}
7356+
llvm::Value *d;
7357+
d = builder->CreateFPExt(complex_re(tmp, complex_type), type);
7358+
args.push_back(d);
7359+
d = builder->CreateFPExt(complex_im(tmp, complex_type), type);
7360+
args.push_back(d);
7361+
} else if (t->type == ASR::ttypeType::CPtr) {
7362+
fmt.push_back("%lld");
7363+
llvm::Value* d = builder->CreatePtrToInt(tmp, getIntType(8, false));
7364+
args.push_back(d);
7365+
} else if (t->type == ASR::ttypeType::Enum) {
7366+
// TODO: Use recursion to generalise for any underlying type in enum
7367+
fmt.push_back("%d");
7368+
args.push_back(tmp);
7369+
} else {
7370+
throw CodeGenError("Printing support is not available for `" +
7371+
ASRUtils::type_to_str(t) + "` type.", loc);
7372+
}
7373+
}
7374+
72107375
template <typename T>
72117376
void handle_print(const T &x) {
72127377
std::vector<llvm::Value *> args;
@@ -7226,174 +7391,11 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor<ASRToLLVMVisitor>
72267391
end = builder->CreateGlobalStringPtr("\n");
72277392
}
72287393
for (size_t i=0; i<x.n_values; i++) {
7229-
int64_t ptr_loads_copy = ptr_loads;
7230-
int reduce_loads = 0;
7231-
ptr_loads = 2;
7232-
if( ASR::is_a<ASR::Var_t>(*x.m_values[i]) ) {
7233-
ASR::Variable_t* var = ASRUtils::EXPR2VAR(x.m_values[i]);
7234-
reduce_loads = var->m_intent == ASRUtils::intent_in;
7235-
if( ASR::is_a<ASR::Pointer_t>(*var->m_type) ) {
7236-
ptr_loads = 1;
7237-
}
7238-
}
72397394
if (i != 0) {
72407395
fmt.push_back("%s");
72417396
args.push_back(sep);
72427397
}
7243-
ptr_loads = ptr_loads - reduce_loads;
7244-
lookup_enum_value_for_nonints = true;
7245-
this->visit_expr_wrapper(x.m_values[i], true);
7246-
lookup_enum_value_for_nonints = false;
7247-
ptr_loads = ptr_loads_copy;
7248-
ASR::expr_t *v = x.m_values[i];
7249-
ASR::ttype_t *t = ASRUtils::type_get_past_allocatable(ASRUtils::expr_type(v));
7250-
if( ASR::is_a<ASR::Const_t>(*t) ) {
7251-
t = ASRUtils::get_contained_type(t);
7252-
}
7253-
t = ASRUtils::type_get_past_allocatable(t);
7254-
int a_kind = ASRUtils::extract_kind_from_ttype_t(t);
7255-
if( ASR::is_a<ASR::Pointer_t>(*t) && ASR::is_a<ASR::Var_t>(*v) ) {
7256-
if( ASRUtils::is_array(ASRUtils::type_get_past_pointer(t)) ) {
7257-
tmp = CreateLoad(arr_descr->get_pointer_to_data(tmp));
7258-
}
7259-
fmt.push_back("%lld");
7260-
llvm::Value* d = builder->CreatePtrToInt(tmp, getIntType(8, false));
7261-
args.push_back(d);
7262-
continue;
7263-
}
7264-
if (t->type == ASR::ttypeType::CPtr ||
7265-
(t->type == ASR::ttypeType::Pointer &&
7266-
(ASR::is_a<ASR::Var_t>(*v) || ASR::is_a<ASR::GetPointer_t>(*v)))
7267-
) {
7268-
fmt.push_back("%lld");
7269-
llvm::Value* d = builder->CreatePtrToInt(tmp, getIntType(8, false));
7270-
args.push_back(d);
7271-
} else if (ASRUtils::is_integer(*t)) {
7272-
switch( a_kind ) {
7273-
case 1 : {
7274-
fmt.push_back("%hhi");
7275-
break;
7276-
}
7277-
case 2 : {
7278-
fmt.push_back("%hi");
7279-
break;
7280-
}
7281-
case 4 : {
7282-
fmt.push_back("%d");
7283-
break;
7284-
}
7285-
case 8 : {
7286-
fmt.push_back("%lld");
7287-
break;
7288-
}
7289-
default: {
7290-
throw CodeGenError(R"""(Printing support is available only
7291-
for 8, 16, 32, and 64 bit integer kinds.)""",
7292-
x.base.base.loc);
7293-
}
7294-
}
7295-
args.push_back(tmp);
7296-
} else if (ASRUtils::is_unsigned_integer(*t)) {
7297-
switch( a_kind ) {
7298-
case 1 : {
7299-
fmt.push_back("%hhu");
7300-
break;
7301-
}
7302-
case 2 : {
7303-
fmt.push_back("%hu");
7304-
break;
7305-
}
7306-
case 4 : {
7307-
fmt.push_back("%u");
7308-
break;
7309-
}
7310-
case 8 : {
7311-
fmt.push_back("%llu");
7312-
break;
7313-
}
7314-
default: {
7315-
throw CodeGenError(R"""(Printing support is available only
7316-
for 8, 16, 32, and 64 bit unsigned integer kinds.)""",
7317-
x.base.base.loc);
7318-
}
7319-
}
7320-
args.push_back(tmp);
7321-
} else if (ASRUtils::is_real(*t)) {
7322-
llvm::Value *d;
7323-
switch( a_kind ) {
7324-
case 4 : {
7325-
// Cast float to double as a workaround for the fact that
7326-
// vprintf() seems to cast to double even for %f, which
7327-
// causes it to print 0.000000.
7328-
fmt.push_back("%13.8e");
7329-
d = builder->CreateFPExt(tmp,
7330-
llvm::Type::getDoubleTy(context));
7331-
break;
7332-
}
7333-
case 8 : {
7334-
fmt.push_back("%23.17e");
7335-
d = builder->CreateFPExt(tmp,
7336-
llvm::Type::getDoubleTy(context));
7337-
break;
7338-
}
7339-
default: {
7340-
throw CodeGenError(R"""(Printing support is available only
7341-
for 32, and 64 bit real kinds.)""",
7342-
x.base.base.loc);
7343-
}
7344-
}
7345-
args.push_back(d);
7346-
} else if (t->type == ASR::ttypeType::Character) {
7347-
fmt.push_back("%s");
7348-
args.push_back(tmp);
7349-
} else if (ASRUtils::is_logical(*t)) {
7350-
llvm::Value *cmp = builder->CreateICmpEQ(tmp, builder->getInt1(0));
7351-
llvm::Value *zero_str = builder->CreateGlobalStringPtr("False");
7352-
llvm::Value *one_str = builder->CreateGlobalStringPtr("True");
7353-
llvm::Value *str = builder->CreateSelect(cmp, zero_str, one_str);
7354-
fmt.push_back("%s");
7355-
args.push_back(str);
7356-
} else if (ASRUtils::is_complex(*t)) {
7357-
llvm::Type *type, *complex_type;
7358-
switch( a_kind ) {
7359-
case 4 : {
7360-
// Cast float to double as a workaround for the fact that
7361-
// vprintf() seems to cast to double even for %f, which
7362-
// causes it to print 0.000000.
7363-
fmt.push_back("(%f,%f)");
7364-
type = llvm::Type::getDoubleTy(context);
7365-
complex_type = complex_type_4;
7366-
break;
7367-
}
7368-
case 8 : {
7369-
fmt.push_back("(%lf,%lf)");
7370-
type = llvm::Type::getDoubleTy(context);
7371-
complex_type = complex_type_8;
7372-
break;
7373-
}
7374-
default: {
7375-
throw CodeGenError(R"""(Printing support is available only
7376-
for 32, and 64 bit complex kinds.)""",
7377-
x.base.base.loc);
7378-
}
7379-
}
7380-
llvm::Value *d;
7381-
d = builder->CreateFPExt(complex_re(tmp, complex_type), type);
7382-
args.push_back(d);
7383-
d = builder->CreateFPExt(complex_im(tmp, complex_type), type);
7384-
args.push_back(d);
7385-
} else if (t->type == ASR::ttypeType::CPtr) {
7386-
fmt.push_back("%lld");
7387-
llvm::Value* d = builder->CreatePtrToInt(tmp, getIntType(8, false));
7388-
args.push_back(d);
7389-
} else if (t->type == ASR::ttypeType::Enum) {
7390-
// TODO: Use recursion to generalise for any underlying type in enum
7391-
fmt.push_back("%d");
7392-
args.push_back(tmp);
7393-
} else {
7394-
throw CodeGenError("Printing support is not available for `" +
7395-
ASRUtils::type_to_str(t) + "` type.", x.base.base.loc);
7396-
}
7398+
compute_fmt_specifier_and_arg(fmt, args, x.m_values[i], x.base.base.loc);
73977399
}
73987400
fmt.push_back("%s");
73997401
args.push_back(end);

0 commit comments

Comments
 (0)