1- use crate :: constant:: ConstantRef ;
1+ use crate :: constant:: { Constant , ConstantRef } ;
22use crate :: debugloc:: { DebugLoc , HasDebugLoc } ;
33use crate :: function:: { CallingConvention , FunctionAttribute , ParameterAttribute } ;
44use crate :: name:: Name ;
5- use crate :: operand:: Operand ;
5+ use crate :: operand:: { fmt_operand_value , fmt_operand_with_attrs , Operand } ;
66use crate :: predicates:: * ;
77#[ cfg( feature = "llvm-14-or-lower" ) ]
88use crate :: types:: NamedStructDef ;
@@ -631,11 +631,8 @@ macro_rules! binop_display {
631631 ( $inst: ty, $dispname: expr) => {
632632 impl Display for $inst {
633633 fn fmt( & self , f: & mut fmt:: Formatter ) -> fmt:: Result {
634- write!(
635- f,
636- "{} = {} {}, {}" ,
637- & self . dest, $dispname, & self . operand0, & self . operand1,
638- ) ?;
634+ write!( f, "{} = {} {}, " , & self . dest, $dispname, & self . operand0) ?;
635+ fmt_operand_value( & self . operand1, f) ?;
639636 if self . debugloc. is_some( ) {
640637 write!( f, " (with debugloc)" ) ?;
641638 }
@@ -662,11 +659,8 @@ macro_rules! binop_display_with_flags {
662659 // Write any flags we may have
663660 $( #[ cfg( feature = $required_feature) ] if self . $flag_field { write!( f, " {}" , $flag_display) ?; } ) *
664661
665- write!(
666- f,
667- " {}, {}" ,
668- & self . operand0, & self . operand1,
669- ) ?;
662+ write!( f, " {}, " , & self . operand0) ?;
663+ fmt_operand_value( & self . operand1, f) ?;
670664
671665 if self . debugloc. is_some( ) {
672666 write!( f, " (with debugloc)" ) ?;
@@ -1711,14 +1705,14 @@ fn gep_type<'o>(
17111705
17121706impl Display for GetElementPtr {
17131707 fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
1714- // Like for `Load` (see notes there), we differ from the LLVM IR text
1715- // syntax here because we don't include the destination type (that's a
1716- // little hard to get for us here, and it's derivable from the other
1717- // information anyway)
17181708 write ! ( f, "{} = getelementptr " , & self . dest) ?;
17191709 if self . in_bounds {
17201710 write ! ( f, "inbounds " ) ?;
17211711 }
1712+ #[ cfg( feature = "llvm-14-or-greater" ) ]
1713+ {
1714+ write ! ( f, "{}, " , & self . source_element_type) ?;
1715+ }
17221716 write ! ( f, "{}" , & self . address) ?;
17231717 for idx in & self . indices {
17241718 write ! ( f, ", {}" , idx) ?;
@@ -1951,11 +1945,8 @@ impl Typed for ICmp {
19511945
19521946impl Display for ICmp {
19531947 fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
1954- write ! (
1955- f,
1956- "{} = icmp {} {}, {}" ,
1957- & self . dest, & self . predicate, & self . operand0, & self . operand1,
1958- ) ?;
1948+ write ! ( f, "{} = icmp {} {}, " , & self . dest, & self . predicate, & self . operand0) ?;
1949+ fmt_operand_value ( & self . operand1 , f) ?;
19591950 if self . debugloc . is_some ( ) {
19601951 write ! ( f, " (with debugloc)" ) ?;
19611952 }
@@ -1998,11 +1989,8 @@ impl Typed for FCmp {
19981989
19991990impl Display for FCmp {
20001991 fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
2001- write ! (
2002- f,
2003- "{} = fcmp {} {}, {}" ,
2004- & self . dest, & self . predicate, & self . operand0, & self . operand1,
2005- ) ?;
1992+ write ! ( f, "{} = fcmp {} {}, " , & self . dest, & self . predicate, & self . operand0) ?;
1993+ fmt_operand_value ( & self . operand1 , f) ?;
20061994 if self . debugloc . is_some ( ) {
20071995 write ! ( f, " (with debugloc)" ) ?;
20081996 }
@@ -2030,13 +2018,13 @@ impl Display for Phi {
20302018 . incoming_values
20312019 . get ( 0 )
20322020 . expect ( "Phi with no incoming values" ) ;
2033- write ! (
2034- f,
2035- "{} = phi {} [ {}, {} ]" ,
2036- & self . dest, & self . to_type, first_val, first_label,
2037- ) ?;
2021+ write ! ( f, "{} = phi {} [ " , & self . dest, & self . to_type) ?;
2022+ fmt_operand_value ( first_val, f) ?;
2023+ write ! ( f, ", {} ]" , first_label) ?;
20382024 for ( val, label) in & self . incoming_values [ 1 ..] {
2039- write ! ( f, ", [ {}, {} ]" , val, label) ?;
2025+ write ! ( f, ", [ " ) ?;
2026+ fmt_operand_value ( val, f) ?;
2027+ write ! ( f, ", {} ]" , label) ?;
20402028 }
20412029 if self . debugloc . is_some ( ) {
20422030 write ! ( f, " (with debugloc)" ) ?;
@@ -2141,30 +2129,75 @@ impl Typed for Call {
21412129
21422130impl Display for Call {
21432131 fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
2144- // We choose not to include all the detailed information available in
2145- // the `Call` struct in this `Display` impl
21462132 if let Some ( dest) = & self . dest {
21472133 write ! ( f, "{} = " , dest) ?;
21482134 }
21492135 if self . is_tail_call {
21502136 write ! ( f, "tail " ) ?;
21512137 }
2152- write ! (
2153- f,
2154- "call {}(" ,
2155- match & self . function {
2156- Either :: Left ( _) => "<inline assembly>" . into( ) ,
2157- Either :: Right ( op) => format!( "{}" , op) ,
2138+ write ! ( f, "call " ) ?;
2139+ let cc = self . calling_convention . to_string ( ) ;
2140+ if !cc. is_empty ( ) {
2141+ write ! ( f, "{} " , cc) ?;
2142+ }
2143+ for attr in & self . return_attributes {
2144+ let s = attr. to_string ( ) ;
2145+ if !s. is_empty ( ) {
2146+ write ! ( f, "{} " , s) ?;
21582147 }
2159- ) ?;
2160- for ( i, ( arg, _) ) in self . arguments . iter ( ) . enumerate ( ) {
2161- if i == self . arguments . len ( ) - 1 {
2162- write ! ( f, "{}" , arg) ?;
2163- } else {
2164- write ! ( f, "{}, " , arg) ?;
2148+ }
2149+ // For LLVM 15+, emit the function type (or return type for simple calls)
2150+ // For LLVM 14 and lower, the pointer type includes the pointee (function) type
2151+ #[ cfg( feature = "llvm-15-or-greater" ) ]
2152+ {
2153+ match self . function_ty . as_ref ( ) {
2154+ Type :: FuncType { result_type, is_var_arg, .. } if * is_var_arg => {
2155+ // varargs: must emit the full function type
2156+ write ! ( f, "{} " , self . function_ty) ?;
2157+ } ,
2158+ Type :: FuncType { result_type, .. } => {
2159+ write ! ( f, "{} " , result_type) ?;
2160+ } ,
2161+ _ => {
2162+ write ! ( f, "{} " , self . function_ty) ?;
2163+ } ,
21652164 }
21662165 }
2166+ // Write the callee
2167+ match & self . function {
2168+ Either :: Left ( _) => write ! ( f, "<inline assembly>" ) ?,
2169+ Either :: Right ( Operand :: ConstantOperand ( cref) ) => {
2170+ match cref. as_ref ( ) {
2171+ Constant :: GlobalReference { name, .. } => {
2172+ match name {
2173+ Name :: Name ( n) => write ! ( f, "@{}" , n) ?,
2174+ Name :: Number ( n) => write ! ( f, "@{}" , n) ?,
2175+ }
2176+ } ,
2177+ _ => write ! ( f, "{}" , cref) ?,
2178+ }
2179+ } ,
2180+ #[ cfg( feature = "llvm-14-or-lower" ) ]
2181+ Either :: Right ( op) => write ! ( f, "{}" , op) ?,
2182+ #[ cfg( feature = "llvm-15-or-greater" ) ]
2183+ Either :: Right ( Operand :: LocalOperand { name, .. } ) => write ! ( f, "{}" , name) ?,
2184+ #[ cfg( feature = "llvm-15-or-greater" ) ]
2185+ Either :: Right ( op) => write ! ( f, "{}" , op) ?,
2186+ }
2187+ write ! ( f, "(" ) ?;
2188+ for ( i, ( arg, attrs) ) in self . arguments . iter ( ) . enumerate ( ) {
2189+ if i > 0 {
2190+ write ! ( f, ", " ) ?;
2191+ }
2192+ fmt_operand_with_attrs ( arg, attrs, f) ?;
2193+ }
21672194 write ! ( f, ")" ) ?;
2195+ for attr in & self . function_attributes {
2196+ let s = attr. to_string ( ) ;
2197+ if !s. is_empty ( ) {
2198+ write ! ( f, " {}" , s) ?;
2199+ }
2200+ }
21682201 if self . debugloc . is_some ( ) {
21692202 write ! ( f, " (with debugloc)" ) ?;
21702203 }
@@ -2503,7 +2536,6 @@ pub struct LandingPadClause {}
25032536// from_llvm //
25042537// ********* //
25052538
2506- use crate :: constant:: Constant ;
25072539use crate :: from_llvm:: * ;
25082540use crate :: function:: FunctionContext ;
25092541use crate :: llvm_sys:: * ;
0 commit comments