@@ -2648,6 +2648,189 @@ 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+ vector<ValueLocation> GetParameterLocations (const std::optional<ValueLocation>& returnValue,
2673+ const vector<FunctionParameter>& params, const std::optional<set<uint32_t >>& permittedRegs) override
2674+ {
2675+ vector<ValueLocation> result;
2676+ result.reserve (params.size ());
2677+
2678+ vector<uint32_t > intArgs = GetIntegerArgumentRegisters ();
2679+ vector<uint32_t > floatArgs = GetFloatArgumentRegisters ();
2680+
2681+ auto intArgIter = intArgs.begin ();
2682+ auto floatArgIter = floatArgs.begin ();
2683+ int64_t stackOffset = 0 ;
2684+
2685+ for (auto & param : params)
2686+ {
2687+ size_t width = param.type ->GetWidth ();
2688+
2689+ if (!param.defaultLocation )
2690+ {
2691+ // Parameter not storage in a normal location, use custom variable
2692+ result.push_back (param.location );
2693+ for (auto & component : param.location .components )
2694+ {
2695+ if (component.indirect )
2696+ continue ;
2697+
2698+ if (component.variable .type == RegisterVariableSourceType)
2699+ {
2700+ // If non-default location matches the next register in the register parameter
2701+ // lists, advance the iterators. It may just be a type mismatch, and we still
2702+ // want to maintain the state for future parameters.
2703+ if (intArgIter != intArgs.end () && *intArgIter == component.variable .storage )
2704+ intArgIter++;
2705+ else if (floatArgIter != floatArgs.end () && *floatArgIter == component.variable .storage )
2706+ floatArgIter++;
2707+ }
2708+ else if (component.variable .type == StackVariableSourceType
2709+ && component.variable .storage >= stackOffset)
2710+ {
2711+ // Adjust next automatic stack location to after this one
2712+ stackOffset = component.variable .storage ;
2713+ if (width < 8 )
2714+ width = 8 ;
2715+ else if ((width % 8 ) != 0 )
2716+ width += 8 - (width % 8 );
2717+ stackOffset += width;
2718+ }
2719+ }
2720+ continue ;
2721+ }
2722+
2723+ bool indirect = false ;
2724+ size_t finalWidth = width;
2725+ if (width > 16 )
2726+ {
2727+ indirect = true ;
2728+ finalWidth = 8 ;
2729+ }
2730+
2731+ if (finalWidth <= 8 )
2732+ {
2733+ if (!indirect && param.type ->IsFloat ())
2734+ {
2735+ if (permittedRegs.has_value () && floatArgIter != floatArgs.end ()
2736+ && permittedRegs.value ().count (*floatArgIter) == 0 )
2737+ {
2738+ // Disallowed register parameter, start spilling to stack. This is used in calling
2739+ // conventions that place all variable argument parameters on the stack.
2740+ floatArgIter = floatArgs.end ();
2741+ }
2742+ else if (floatArgIter != floatArgs.end ())
2743+ {
2744+ BNRegisterInfo regInfo = GetArchitecture ()->GetRegisterInfo (*floatArgIter);
2745+ if (finalWidth <= regInfo.size )
2746+ {
2747+ result.emplace_back (RegisterVariableSourceType, 0 , *floatArgIter);
2748+ floatArgIter++;
2749+ continue ;
2750+ }
2751+ }
2752+ }
2753+ else
2754+ {
2755+ if (permittedRegs.has_value () && intArgIter != intArgs.end ()
2756+ && permittedRegs.value ().count (*intArgIter) == 0 )
2757+ {
2758+ // Disallowed register parameter, start spilling to stack. This is used in calling
2759+ // conventions that place all variable argument parameters on the stack.
2760+ intArgIter = intArgs.end ();
2761+ }
2762+ else if (intArgIter != intArgs.end ())
2763+ {
2764+ BNRegisterInfo regInfo = GetArchitecture ()->GetRegisterInfo (*intArgIter);
2765+ if (finalWidth <= regInfo.size )
2766+ {
2767+ if (indirect)
2768+ {
2769+ result.push_back (ValueLocation ({ValueLocationComponent (
2770+ Variable (RegisterVariableSourceType, 0 , *intArgIter), 0 , width, true )}));
2771+ }
2772+ else
2773+ {
2774+ result.emplace_back (RegisterVariableSourceType, 0 , *intArgIter);
2775+ }
2776+ intArgIter++;
2777+ continue ;
2778+ }
2779+ }
2780+ }
2781+ }
2782+ else if (finalWidth <= 16 )
2783+ {
2784+ if (permittedRegs.has_value () && intArgIter != intArgs.end ()
2785+ && permittedRegs.value ().count (*intArgIter) == 0 )
2786+ {
2787+ // Disallowed register parameter, start spilling to stack. This is used in calling
2788+ // conventions that place all variable argument parameters on the stack.
2789+ intArgIter = intArgs.end ();
2790+ }
2791+ else if (intArgIter != intArgs.end ())
2792+ {
2793+ uint32_t first = *intArgIter;
2794+ intArgIter++;
2795+ if (permittedRegs.has_value () && intArgIter != intArgs.end ()
2796+ && permittedRegs.value ().count (*intArgIter) == 0 )
2797+ {
2798+ // Disallowed register parameter, start spilling to stack. This is used in calling
2799+ // conventions that place all variable argument parameters on the stack.
2800+ intArgIter = intArgs.end ();
2801+ }
2802+ else if (intArgIter != intArgs.end ())
2803+ {
2804+ uint32_t second = *intArgIter;
2805+ intArgIter++;
2806+ result.push_back (
2807+ ValueLocation ({ValueLocationComponent (Variable (RegisterVariableSourceType, 0 , first), 0 , 8 ),
2808+ ValueLocationComponent (
2809+ Variable (RegisterVariableSourceType, 0 , second), 8 , finalWidth - 8 )}));
2810+ continue ;
2811+ }
2812+ }
2813+ }
2814+
2815+ if (indirect)
2816+ {
2817+ result.push_back (ValueLocation (
2818+ {ValueLocationComponent (Variable (StackVariableSourceType, 0 , stackOffset), 0 , width, true )}));
2819+ }
2820+ else
2821+ {
2822+ result.emplace_back (StackVariableSourceType, 0 , stackOffset);
2823+ }
2824+
2825+ if (finalWidth < 8 )
2826+ finalWidth = 8 ;
2827+ else if ((finalWidth % 8 ) != 0 )
2828+ finalWidth += 8 - (finalWidth % 8 );
2829+ stackOffset += finalWidth;
2830+ }
2831+
2832+ return result;
2833+ }
26512834};
26522835
26532836
0 commit comments