@@ -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