- 
                Notifications
    You must be signed in to change notification settings 
- Fork 13.9k
          Refactor the way cg_ssa handles indirect returns(returns via sret). 
          #144976
        
          New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | 
|---|---|---|
|  | @@ -600,6 +600,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { | |
| fn_attrs: Option<&CodegenFnAttrs>, | ||
| _fn_abi: Option<&FnAbi<'tcx, Ty<'tcx>>>, | ||
| func: RValue<'gcc>, | ||
| indirect_return_pointer: Option<RValue<'gcc>>, | ||
| args: &[RValue<'gcc>], | ||
| then: Block<'gcc>, | ||
| catch: Block<'gcc>, | ||
|  | @@ -610,7 +611,8 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { | |
|  | ||
| let current_block = self.block; | ||
| self.block = try_block; | ||
| let call = self.call(typ, fn_attrs, None, func, args, None, instance); // TODO(antoyo): use funclet here? | ||
| let call = | ||
| self.call(typ, fn_attrs, None, func, indirect_return_pointer, args, None, instance); // TODO(antoyo): use funclet here? | ||
| 
      Comment on lines
    
      -613
     to 
      +615
    
   There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. please break the comment onto the preceding line. | ||
| self.block = current_block; | ||
|  | ||
| let return_value = | ||
|  | @@ -638,13 +640,15 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { | |
| fn_attrs: Option<&CodegenFnAttrs>, | ||
| fn_abi: Option<&FnAbi<'tcx, Ty<'tcx>>>, | ||
| func: RValue<'gcc>, | ||
| indirect_return_pointer: Option<RValue<'gcc>>, | ||
| args: &[RValue<'gcc>], | ||
| then: Block<'gcc>, | ||
| catch: Block<'gcc>, | ||
| _funclet: Option<&Funclet>, | ||
| instance: Option<Instance<'tcx>>, | ||
| ) -> RValue<'gcc> { | ||
| let call_site = self.call(typ, fn_attrs, None, func, args, None, instance); | ||
| let call_site = | ||
| self.call(typ, fn_attrs, None, func, indirect_return_pointer, args, None, instance); | ||
| let condition = self.context.new_rvalue_from_int(self.bool_type, 1); | ||
| self.llbb().end_with_conditional(self.location, condition, then, catch); | ||
| if let Some(_fn_abi) = fn_abi { | ||
|  | @@ -1739,17 +1743,28 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { | |
| _fn_attrs: Option<&CodegenFnAttrs>, | ||
| fn_abi: Option<&FnAbi<'tcx, Ty<'tcx>>>, | ||
| func: RValue<'gcc>, | ||
| indirect_return_pointer: Option<RValue<'gcc>>, | ||
| args: &[RValue<'gcc>], | ||
| funclet: Option<&Funclet>, | ||
| _instance: Option<Instance<'tcx>>, | ||
| ) -> RValue<'gcc> { | ||
| // FIXME: change this in the `rustc_codegen_gcc` repo after the sync, to use the `libgccjit` indirect return suppport. | ||
| let args = match indirect_return_pointer { | ||
| None => args.to_vec(), | ||
| Some(sret_ptr) => { | ||
| let mut args = args.to_vec(); | ||
| // Preappend the indirect return pointer | ||
|         
                  FractalFir marked this conversation as resolved.
              Outdated
          
            Show resolved
            Hide resolved | ||
| args.insert(0, sret_ptr); | ||
| args | ||
| } | ||
| }; | ||
| // FIXME(antoyo): remove when having a proper API. | ||
| let gcc_func = unsafe { std::mem::transmute::<RValue<'gcc>, Function<'gcc>>(func) }; | ||
| let call = if self.functions.borrow().values().any(|value| *value == gcc_func) { | ||
| self.function_call(func, args, funclet) | ||
| self.function_call(func, &args, funclet) | ||
| } else { | ||
| // If it's a not function that was defined, it's a function pointer. | ||
| self.function_ptr_call(typ, func, args, funclet) | ||
| self.function_ptr_call(typ, func, &args, funclet) | ||
| }; | ||
| if let Some(_fn_abi) = fn_abi { | ||
| // TODO(bjorn3): Apply function attributes | ||
|  | ||
| Original file line number | Diff line number | Diff line change | 
|---|---|---|
|  | @@ -644,7 +644,16 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc | |
| fn abort(&mut self) { | ||
| let func = self.context.get_builtin_function("abort"); | ||
| let func: RValue<'gcc> = unsafe { std::mem::transmute(func) }; | ||
| self.call(self.type_void(), None, None, func, &[], None, None); | ||
| self.call( | ||
| self.type_void(), | ||
| None, | ||
| None, | ||
| func, | ||
| None, /* abort does not return, so it can't return indirectly. */ | ||
| &[], | ||
| None, | ||
| None, | ||
| ); | ||
| } | ||
|  | ||
| fn assume(&mut self, value: Self::Value) { | ||
|  | @@ -1340,7 +1349,16 @@ fn try_intrinsic<'a, 'b, 'gcc, 'tcx>( | |
| dest: PlaceRef<'tcx, RValue<'gcc>>, | ||
| ) { | ||
| if bx.sess().panic_strategy() == PanicStrategy::Abort { | ||
| bx.call(bx.type_void(), None, None, try_func, &[data], None, None); | ||
| bx.call( | ||
| bx.type_void(), | ||
| None, | ||
| None, | ||
| try_func, | ||
| None, /* This intrinsic does not return indirectly.*/ | ||
| &[data], | ||
| None, | ||
| None, | ||
| ); | ||
| // Return 0 unconditionally from the intrinsic call; | ||
| // we can never unwind. | ||
| OperandValue::Immediate(bx.const_i32(0)).store(bx, dest); | ||
|  | @@ -1413,21 +1431,50 @@ fn codegen_gnu_try<'gcc, 'tcx>( | |
| let zero = bx.cx.context.new_rvalue_zero(bx.int_type); | ||
| let ptr = bx.cx.context.new_call(None, eh_pointer_builtin, &[zero]); | ||
| let catch_ty = bx.type_func(&[bx.type_i8p(), bx.type_i8p()], bx.type_void()); | ||
| bx.call(catch_ty, None, None, catch_func, &[data, ptr], None, None); | ||
| bx.call( | ||
| catch_ty, | ||
| None, | ||
| None, | ||
| catch_func, | ||
| None, /* this function can't return indirectly */ | ||
| There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. if there is going to be a comment, then please answer "why can't it?" instead of a statement that it doesn't return indirectly. | ||
| &[data, ptr], | ||
| None, | ||
| None, | ||
| ); | ||
| bx.ret(bx.const_i32(1)); | ||
|  | ||
| // NOTE: the blocks must be filled before adding the try/catch, otherwise gcc will not | ||
| // generate a try/catch. | ||
| // FIXME(antoyo): add a check in the libgccjit API to prevent this. | ||
| bx.switch_to_block(current_block); | ||
| bx.invoke(try_func_ty, None, None, try_func, &[data], then, catch, None, None); | ||
| bx.invoke( | ||
| try_func_ty, | ||
| None, | ||
| None, | ||
| try_func, | ||
| None, /* this function can't return indirectly */ | ||
| &[data], | ||
| then, | ||
| catch, | ||
| None, | ||
| None, | ||
| ); | ||
| }); | ||
|  | ||
| let func = unsafe { std::mem::transmute::<Function<'gcc>, RValue<'gcc>>(func) }; | ||
|  | ||
| // Note that no invoke is used here because by definition this function | ||
| // can't panic (that's what it's catching). | ||
| let ret = bx.call(llty, None, None, func, &[try_func, data, catch_func], None, None); | ||
| let ret = bx.call( | ||
| llty, | ||
| None, | ||
| None, | ||
| func, | ||
| None, /*This function can't return indirectly*/ | ||
| &[try_func, data, catch_func], | ||
| None, | ||
| None, | ||
| ); | ||
| OperandValue::Immediate(ret).store(bx, dest); | ||
| } | ||
|  | ||
|  | ||
Uh oh!
There was an error while loading. Please reload this page.