@@ -298,29 +298,185 @@ vector<uint32_t> CallingConvention::GetFloatArgumentRegisters()
298298
299299vector<uint32_t > CallingConvention::GetRegisterArgumentClasses ()
300300{
301- return vector<uint32_t >();
301+ /*
302+ This should return vector<uint32_t> {} when all architecture
303+ supports register class and register list.
304+ */
305+ if (AreArgumentRegistersSharedIndex ())
306+ return vector<uint32_t > {0 };
307+
308+ return vector<uint32_t > {0 , 1 };
302309}
303310
304311
305312vector<uint32_t > CallingConvention::GetRegisterArgumentClassLists (uint32_t classId)
306313{
307- return vector<uint32_t >();
314+ /*
315+ This should return vector<uint32_t> {} when all architecture
316+ supports register class and register list.
317+ */
318+ if (AreArgumentRegistersSharedIndex ()) {
319+ return vector<uint32_t > {0 , 1 };
320+ } else {
321+ if (0 == classId) {
322+ return vector<uint32_t > {0 };
323+ } else if (1 == classId) {
324+ return vector<uint32_t > {1 };
325+ }
326+ }
327+ return vector<uint32_t > {};
308328}
309329
310330
311331vector<uint32_t > CallingConvention::GetRegisterArgumentLists ()
312332{
313- // Default implementation: derive from classes
314- return vector<uint32_t >();
333+ vector<uint32_t > result;
334+ vector<uint32_t > classes = GetRegisterArgumentClasses ();
335+ for (uint32_t classId : classes)
336+ {
337+ vector<uint32_t > lists = GetRegisterArgumentClassLists (classId);
338+ result.insert (result.end (), lists.begin (), lists.end ());
339+ }
340+ return result;
315341}
316342
317343
318344vector<uint32_t > CallingConvention::GetRegisterArgumentListRegs (uint32_t regListId)
319345{
320- // Default implementation: no registers for any list
346+ /*
347+ This should return vector<uint32_t> {} when all architecture
348+ supports register class and register list.
349+
350+ Bridge implementation: use old APIs as fallback for architectures that haven't
351+ implemented the new register list/class APIs yet
352+ */
353+ if (regListId == 0 ) {
354+ return GetIntegerArgumentRegisters ();
355+ } else if (regListId == 1 ) {
356+ return GetFloatArgumentRegisters ();
357+ }
321358 return vector<uint32_t >();
322359}
323360
361+ vector<Variable> CallingConvention::GetVariablesForParameters (
362+ const vector<FunctionParameter>& params, const std::optional<set<uint32_t >>& permittedRegs)
363+ {
364+ vector<uint32_t > intArgs = GetIntegerArgumentRegisters ();
365+ vector<uint32_t > floatArgs = GetFloatArgumentRegisters ();
366+
367+ vector<Variable> result;
368+ auto intArgIter = intArgs.begin ();
369+ auto floatArgIter = floatArgs.begin ();
370+ size_t addrSize = GetArchitecture ()->GetAddressSize ();
371+ int64_t stackOffset = 0 ;
372+ bool sharedIndex = AreArgumentRegistersSharedIndex ();
373+ if (GetArchitecture ()->GetLinkRegister () == BN_INVALID_REGISTER)
374+ stackOffset = addrSize;
375+ if (IsStackReservedForArgumentRegisters ())
376+ stackOffset += intArgs.size () * addrSize;
377+
378+
379+ // TODO: Structure in register and multi-reg parameters
380+ for (auto & param : params)
381+ {
382+ size_t width = param.type ->GetWidth ();
383+
384+ if (!param.defaultLocation )
385+ {
386+ // Parameter not storage in a normal location, use custom variable
387+ result.push_back (param.location );
388+ if (param.location .type == RegisterVariableSourceType)
389+ {
390+ // If non-default location matches the next register in the register parameter
391+ // lists, advance the iterators. It may just be a type mismatch, and we still
392+ // want to maintain the state for future parameters.
393+ if (intArgIter != intArgs.end () && *intArgIter == param.location .storage )
394+ {
395+ intArgIter++;
396+ if (sharedIndex && floatArgIter != floatArgs.end ())
397+ floatArgIter++;
398+ }
399+ else if (floatArgIter != floatArgs.end () && *floatArgIter == param.location .storage )
400+ {
401+ floatArgIter++;
402+ if (sharedIndex && intArgIter != intArgs.end ())
403+ intArgIter++;
404+ }
405+ }
406+ else if (param.location .type == StackVariableSourceType)
407+ {
408+ // Adjust next automatic stack location to after this one
409+ stackOffset = param.location .storage ;
410+ if (width < addrSize)
411+ width = addrSize;
412+ else if ((width % addrSize) != 0 )
413+ width += addrSize - (width % addrSize);
414+ stackOffset += width;
415+ }
416+ continue ;
417+ }
418+
419+ if (param.type ->IsFloat ())
420+ {
421+ if (permittedRegs.has_value () && floatArgIter != floatArgs.end ()
422+ && permittedRegs.value ().count (*floatArgIter) == 0 )
423+ {
424+ // Disallowed register parameter, start spilling to stack. This is used in calling
425+ // conventions that place all variable argument parameters on the stack.
426+ floatArgIter = floatArgs.end ();
427+ if (sharedIndex)
428+ intArgIter = intArgs.end ();
429+ }
430+ else if (floatArgIter != floatArgs.end ())
431+ {
432+ BNRegisterInfo regInfo = GetArchitecture ()->GetRegisterInfo (*floatArgIter);
433+ if (width <= regInfo.size )
434+ {
435+ result.emplace_back (RegisterVariableSourceType, 0 , *floatArgIter);
436+ floatArgIter++;
437+ if (sharedIndex && intArgIter != intArgs.end ())
438+ intArgIter++;
439+ continue ;
440+ }
441+ }
442+ }
443+ else
444+ {
445+ if (permittedRegs.has_value () && intArgIter != intArgs.end ()
446+ && permittedRegs.value ().count (*intArgIter) == 0 )
447+ {
448+ // Disallowed register parameter, start spilling to stack. This is used in calling
449+ // conventions that place all variable argument parameters on the stack.
450+ intArgIter = intArgs.end ();
451+ if (sharedIndex)
452+ floatArgIter = floatArgs.end ();
453+ }
454+ else if (intArgIter != intArgs.end ())
455+ {
456+ BNRegisterInfo regInfo = GetArchitecture ()->GetRegisterInfo (*intArgIter);
457+ if (width <= regInfo.size )
458+ {
459+ result.emplace_back (RegisterVariableSourceType, 0 , *intArgIter);
460+ intArgIter++;
461+ if (sharedIndex && floatArgIter != floatArgs.end ())
462+ floatArgIter++;
463+ continue ;
464+ }
465+ }
466+ }
467+
468+ result.emplace_back (StackVariableSourceType, 0 , stackOffset);
469+
470+ if (width < addrSize)
471+ width = addrSize;
472+ else if ((width % addrSize) != 0 )
473+ width += addrSize - (width % addrSize);
474+ stackOffset += width;
475+ }
476+
477+ return result;
478+ }
479+
324480
325481BNRegisterListKind CallingConvention::GetRegisterArgumentListKind (uint32_t regListId)
326482{
@@ -329,12 +485,6 @@ BNRegisterListKind CallingConvention::GetRegisterArgumentListKind(uint32_t regLi
329485}
330486
331487
332- vector<Variable> CallingConvention::GetVariablesForParameters (const vector<FunctionParameter>& paramTypes,
333- const std::set<uint32_t >* permittedRegs)
334- {
335- return vector<Variable>();
336- }
337-
338488bool CallingConvention::AreArgumentRegistersSharedIndex ()
339489{
340490 return false ;
@@ -608,7 +758,7 @@ BNRegisterListKind CoreCallingConvention::GetRegisterArgumentListKind(uint32_t r
608758
609759
610760vector<Variable> CoreCallingConvention::GetVariablesForParameters (const vector<FunctionParameter>& paramTypes,
611- const std::set<uint32_t >* permittedRegs)
761+ const std::optional<std:: set<uint32_t >>& permittedRegs)
612762{
613763 BNFunctionParameter* params = new BNFunctionParameter[paramTypes.size ()];
614764 for (size_t i = 0 ; i < paramTypes.size (); i++)
@@ -624,12 +774,12 @@ vector<Variable> CoreCallingConvention::GetVariablesForParameters(const vector<F
624774
625775 uint32_t * permittedRegsArray = nullptr ;
626776 size_t permittedRegsCount = 0 ;
627- if (permittedRegs != nullptr )
777+ if (permittedRegs. has_value () )
628778 {
629- permittedRegsCount = permittedRegs-> size ();
779+ permittedRegsCount = permittedRegs. value (). size ();
630780 permittedRegsArray = new uint32_t [permittedRegsCount];
631781 size_t j = 0 ;
632- for (auto reg : * permittedRegs)
782+ for (auto reg : permittedRegs. value () )
633783 permittedRegsArray[j++] = reg;
634784 }
635785
@@ -640,11 +790,11 @@ vector<Variable> CoreCallingConvention::GetVariablesForParameters(const vector<F
640790 vector<Variable> result;
641791 for (size_t i = 0 ; i < count; i++)
642792 result.push_back (vars[i]);
643-
793+ BNFreeVariableList (vars);
794+
644795 delete[] params;
645796 if (permittedRegsArray)
646797 delete[] permittedRegsArray;
647- BNFreeVariableList (vars);
648798 return result;
649799}
650800
@@ -723,34 +873,21 @@ BNVariable* CallingConvention::GetVariablesForParametersCallback(void* ctxt, con
723873 params.push_back (param);
724874 }
725875
726- std::set<uint32_t >* permittedRegsSet = nullptr ;
876+ std::set<uint32_t > regsSet;
877+ std::optional<std::set<uint32_t >> permittedRegsSet;
727878 if (permittedRegs && permittedRegCount > 0 )
728879 {
729- permittedRegsSet = new std::set<uint32_t >();
730880 for (size_t i = 0 ; i < permittedRegCount; i++)
731- permittedRegsSet->insert (permittedRegs[i]);
732- }
733-
734- vector<Variable> variables = cc->GetVariablesForParameters (params, permittedRegsSet);
735-
736- // If the calling convention doesn't implement this method, it returns an empty vector
737- // Signal fallback to core implementation by returning NULL with count 0
738- if (variables.empty ())
739- {
740- *resultCount = 0 ;
741- if (permittedRegsSet)
742- delete permittedRegsSet;
743- return nullptr ;
881+ regsSet.insert (permittedRegs[i]);
882+ permittedRegsSet = regsSet;
744883 }
745884
885+ vector<Variable> variables = cc->GetVariablesForParameters (params, permittedRegsSet);
746886 *resultCount = variables.size ();
747887
748888 BNVariable* result = new BNVariable[variables.size ()];
749889 for (size_t i = 0 ; i < variables.size (); i++)
750890 result[i] = variables[i];
751891
752- if (permittedRegsSet)
753- delete permittedRegsSet;
754-
755892 return result;
756893}
0 commit comments