@@ -2648,6 +2648,209 @@ class Arm64CallingConvention : public CallingConvention
26482648
26492649
26502650 virtual uint32_t GetFloatReturnValueRegister () override { return REG_V0; }
2651+
2652+
2653+ ValueLocation GetReturnValueLocation (const ReturnValue& returnValue) override
2654+ {
2655+ if (returnValue.type ->GetWidth () <= 8 )
2656+ return Variable (RegisterVariableSourceType, 0 , REG_X0);
2657+
2658+ if (returnValue.type ->GetWidth () <= 16 )
2659+ {
2660+ return ValueLocation ({
2661+ ValueLocationComponent (Variable (RegisterVariableSourceType, 0 , REG_X0), 0 , 8 ),
2662+ ValueLocationComponent (
2663+ Variable (RegisterVariableSourceType, 0 , REG_X1), 8 , returnValue.type ->GetWidth () - 8 ),
2664+ });
2665+ }
2666+
2667+ return ValueLocation ({ValueLocationComponent (
2668+ Variable (RegisterVariableSourceType, 0 , REG_X8), 0 , returnValue.type ->GetWidth (), true )});
2669+ }
2670+
2671+
2672+ virtual bool AreStackParametersNaturallyAligned ()
2673+ {
2674+ return false ;
2675+ }
2676+
2677+
2678+ vector<ValueLocation> GetParameterLocations (const std::optional<ValueLocation>& returnValue,
2679+ const vector<FunctionParameter>& params, const std::optional<set<uint32_t >>& permittedRegs) override
2680+ {
2681+ vector<ValueLocation> result;
2682+ result.reserve (params.size ());
2683+
2684+ vector<uint32_t > intArgs = GetIntegerArgumentRegisters ();
2685+ vector<uint32_t > floatArgs = GetFloatArgumentRegisters ();
2686+
2687+ auto intArgIter = intArgs.begin ();
2688+ auto floatArgIter = floatArgs.begin ();
2689+ int64_t stackOffset = 0 ;
2690+
2691+ for (auto & param : params)
2692+ {
2693+ size_t width = param.type ->GetWidth ();
2694+
2695+ if (!param.defaultLocation )
2696+ {
2697+ // Parameter not storage in a normal location, use custom variable
2698+ result.push_back (param.location );
2699+ for (auto & component : param.location .components )
2700+ {
2701+ if (component.indirect )
2702+ continue ;
2703+
2704+ if (component.variable .type == RegisterVariableSourceType)
2705+ {
2706+ // If non-default location matches the next register in the register parameter
2707+ // lists, advance the iterators. It may just be a type mismatch, and we still
2708+ // want to maintain the state for future parameters.
2709+ if (intArgIter != intArgs.end () && *intArgIter == component.variable .storage )
2710+ intArgIter++;
2711+ else if (floatArgIter != floatArgs.end () && *floatArgIter == component.variable .storage )
2712+ floatArgIter++;
2713+ }
2714+ else if (component.variable .type == StackVariableSourceType
2715+ && component.variable .storage >= stackOffset)
2716+ {
2717+ // Adjust next automatic stack location to after this one
2718+ stackOffset = component.variable .storage ;
2719+ if (width < 8 )
2720+ width = 8 ;
2721+ else if ((width % 8 ) != 0 )
2722+ width += 8 - (width % 8 );
2723+ stackOffset += width;
2724+ }
2725+ }
2726+ continue ;
2727+ }
2728+
2729+ bool indirect = false ;
2730+ size_t finalWidth = width;
2731+ if (width > 16 )
2732+ {
2733+ indirect = true ;
2734+ finalWidth = 8 ;
2735+ }
2736+
2737+ if (finalWidth <= 8 )
2738+ {
2739+ if (!indirect && param.type ->IsFloat ())
2740+ {
2741+ if (permittedRegs.has_value () && floatArgIter != floatArgs.end ()
2742+ && permittedRegs.value ().count (*floatArgIter) == 0 )
2743+ {
2744+ // Disallowed register parameter, start spilling to stack. This is used in calling
2745+ // conventions that place all variable argument parameters on the stack.
2746+ floatArgIter = floatArgs.end ();
2747+ }
2748+ else if (floatArgIter != floatArgs.end ())
2749+ {
2750+ BNRegisterInfo regInfo = GetArchitecture ()->GetRegisterInfo (*floatArgIter);
2751+ if (finalWidth <= regInfo.size )
2752+ {
2753+ result.emplace_back (RegisterVariableSourceType, 0 , *floatArgIter);
2754+ floatArgIter++;
2755+ continue ;
2756+ }
2757+ }
2758+ }
2759+ else
2760+ {
2761+ if (permittedRegs.has_value () && intArgIter != intArgs.end ()
2762+ && permittedRegs.value ().count (*intArgIter) == 0 )
2763+ {
2764+ // Disallowed register parameter, start spilling to stack. This is used in calling
2765+ // conventions that place all variable argument parameters on the stack.
2766+ intArgIter = intArgs.end ();
2767+ }
2768+ else if (intArgIter != intArgs.end ())
2769+ {
2770+ BNRegisterInfo regInfo = GetArchitecture ()->GetRegisterInfo (*intArgIter);
2771+ if (finalWidth <= regInfo.size )
2772+ {
2773+ if (indirect)
2774+ {
2775+ result.push_back (ValueLocation ({ValueLocationComponent (
2776+ Variable (RegisterVariableSourceType, 0 , *intArgIter), 0 , width, true )}));
2777+ }
2778+ else
2779+ {
2780+ result.emplace_back (RegisterVariableSourceType, 0 , *intArgIter);
2781+ }
2782+ intArgIter++;
2783+ continue ;
2784+ }
2785+ }
2786+ }
2787+ }
2788+ else if (finalWidth <= 16 )
2789+ {
2790+ if (permittedRegs.has_value () && intArgIter != intArgs.end ()
2791+ && permittedRegs.value ().count (*intArgIter) == 0 )
2792+ {
2793+ // Disallowed register parameter, start spilling to stack. This is used in calling
2794+ // conventions that place all variable argument parameters on the stack.
2795+ intArgIter = intArgs.end ();
2796+ }
2797+ else if (intArgIter != intArgs.end ())
2798+ {
2799+ uint32_t first = *intArgIter;
2800+ intArgIter++;
2801+ if (permittedRegs.has_value () && intArgIter != intArgs.end ()
2802+ && permittedRegs.value ().count (*intArgIter) == 0 )
2803+ {
2804+ // Disallowed register parameter, start spilling to stack. This is used in calling
2805+ // conventions that place all variable argument parameters on the stack.
2806+ intArgIter = intArgs.end ();
2807+ }
2808+ else if (intArgIter != intArgs.end ())
2809+ {
2810+ uint32_t second = *intArgIter;
2811+ intArgIter++;
2812+ result.push_back (
2813+ ValueLocation ({ValueLocationComponent (Variable (RegisterVariableSourceType, 0 , first), 0 , 8 ),
2814+ ValueLocationComponent (
2815+ Variable (RegisterVariableSourceType, 0 , second), 8 , finalWidth - 8 )}));
2816+ continue ;
2817+ }
2818+ }
2819+ }
2820+
2821+ if (indirect)
2822+ {
2823+ result.push_back (ValueLocation (
2824+ {ValueLocationComponent (Variable (StackVariableSourceType, 0 , stackOffset), 0 , width, true )}));
2825+ }
2826+ else
2827+ {
2828+ result.emplace_back (StackVariableSourceType, 0 , stackOffset);
2829+ }
2830+
2831+ if (AreStackParametersNaturallyAligned () && !indirect)
2832+ {
2833+ size_t align = param.type ->GetAlignment ();
2834+ if (align == 0 )
2835+ align = 1 ;
2836+ if (finalWidth < align)
2837+ finalWidth = align;
2838+ else if (finalWidth % align != 0 )
2839+ finalWidth += align - (finalWidth % align);
2840+ stackOffset += finalWidth;
2841+ }
2842+ else
2843+ {
2844+ if (finalWidth < 8 )
2845+ finalWidth = 8 ;
2846+ else if ((finalWidth % 8 ) != 0 )
2847+ finalWidth += 8 - (finalWidth % 8 );
2848+ stackOffset += finalWidth;
2849+ }
2850+ }
2851+
2852+ return result;
2853+ }
26512854};
26522855
26532856
@@ -2663,6 +2866,12 @@ class AppleArm64CallingConvention: public Arm64CallingConvention
26632866 {
26642867 return false ;
26652868 }
2869+
2870+
2871+ virtual bool AreStackParametersNaturallyAligned () override
2872+ {
2873+ return true ;
2874+ }
26662875};
26672876
26682877
0 commit comments