15ffd83dbSDimitry Andric //===-- ABISysV_ppc64.cpp -------------------------------------------------===// 25ffd83dbSDimitry Andric // 35ffd83dbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 45ffd83dbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 55ffd83dbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 65ffd83dbSDimitry Andric // 75ffd83dbSDimitry Andric //===----------------------------------------------------------------------===// 85ffd83dbSDimitry Andric 95ffd83dbSDimitry Andric #include "ABISysV_ppc64.h" 105ffd83dbSDimitry Andric 115ffd83dbSDimitry Andric #include "llvm/ADT/STLExtras.h" 1206c3fb27SDimitry Andric #include "llvm/TargetParser/Triple.h" 135ffd83dbSDimitry Andric 145ffd83dbSDimitry Andric #include "Plugins/TypeSystem/Clang/TypeSystemClang.h" 155ffd83dbSDimitry Andric #include "Utility/PPC64LE_DWARF_Registers.h" 165ffd83dbSDimitry Andric #include "Utility/PPC64_DWARF_Registers.h" 175ffd83dbSDimitry Andric #include "lldb/Core/Module.h" 185ffd83dbSDimitry Andric #include "lldb/Core/PluginManager.h" 195ffd83dbSDimitry Andric #include "lldb/Core/Value.h" 205ffd83dbSDimitry Andric #include "lldb/Core/ValueObjectConstResult.h" 215ffd83dbSDimitry Andric #include "lldb/Core/ValueObjectMemory.h" 225ffd83dbSDimitry Andric #include "lldb/Core/ValueObjectRegister.h" 235ffd83dbSDimitry Andric #include "lldb/Symbol/UnwindPlan.h" 245ffd83dbSDimitry Andric #include "lldb/Target/Process.h" 255ffd83dbSDimitry Andric #include "lldb/Target/RegisterContext.h" 265ffd83dbSDimitry Andric #include "lldb/Target/StackFrame.h" 275ffd83dbSDimitry Andric #include "lldb/Target/Target.h" 285ffd83dbSDimitry Andric #include "lldb/Target/Thread.h" 295ffd83dbSDimitry Andric #include "lldb/Utility/ConstString.h" 305ffd83dbSDimitry Andric #include "lldb/Utility/DataExtractor.h" 3181ad6265SDimitry Andric #include "lldb/Utility/LLDBLog.h" 325ffd83dbSDimitry Andric #include "lldb/Utility/Log.h" 335ffd83dbSDimitry Andric #include "lldb/Utility/RegisterValue.h" 345ffd83dbSDimitry Andric #include "lldb/Utility/Status.h" 355ffd83dbSDimitry Andric 365ffd83dbSDimitry Andric #include "clang/AST/ASTContext.h" 375ffd83dbSDimitry Andric #include "clang/AST/Attr.h" 385ffd83dbSDimitry Andric #include "clang/AST/Decl.h" 395ffd83dbSDimitry Andric 405ffd83dbSDimitry Andric #define DECLARE_REGISTER_INFOS_PPC64_STRUCT 415ffd83dbSDimitry Andric #include "Plugins/Process/Utility/RegisterInfos_ppc64.h" 425ffd83dbSDimitry Andric #undef DECLARE_REGISTER_INFOS_PPC64_STRUCT 435ffd83dbSDimitry Andric 445ffd83dbSDimitry Andric #define DECLARE_REGISTER_INFOS_PPC64LE_STRUCT 455ffd83dbSDimitry Andric #include "Plugins/Process/Utility/RegisterInfos_ppc64le.h" 465ffd83dbSDimitry Andric #undef DECLARE_REGISTER_INFOS_PPC64LE_STRUCT 47bdd1243dSDimitry Andric #include <optional> 485ffd83dbSDimitry Andric 495ffd83dbSDimitry Andric using namespace lldb; 505ffd83dbSDimitry Andric using namespace lldb_private; 515ffd83dbSDimitry Andric 525ffd83dbSDimitry Andric LLDB_PLUGIN_DEFINE(ABISysV_ppc64) 535ffd83dbSDimitry Andric 545ffd83dbSDimitry Andric const lldb_private::RegisterInfo * 555ffd83dbSDimitry Andric ABISysV_ppc64::GetRegisterInfoArray(uint32_t &count) { 565ffd83dbSDimitry Andric if (GetByteOrder() == lldb::eByteOrderLittle) { 57bdd1243dSDimitry Andric count = std::size(g_register_infos_ppc64le); 585ffd83dbSDimitry Andric return g_register_infos_ppc64le; 595ffd83dbSDimitry Andric } else { 60bdd1243dSDimitry Andric count = std::size(g_register_infos_ppc64); 615ffd83dbSDimitry Andric return g_register_infos_ppc64; 625ffd83dbSDimitry Andric } 635ffd83dbSDimitry Andric } 645ffd83dbSDimitry Andric 655ffd83dbSDimitry Andric size_t ABISysV_ppc64::GetRedZoneSize() const { return 224; } 665ffd83dbSDimitry Andric 675ffd83dbSDimitry Andric lldb::ByteOrder ABISysV_ppc64::GetByteOrder() const { 685ffd83dbSDimitry Andric return GetProcessSP()->GetByteOrder(); 695ffd83dbSDimitry Andric } 705ffd83dbSDimitry Andric 715ffd83dbSDimitry Andric // Static Functions 725ffd83dbSDimitry Andric 735ffd83dbSDimitry Andric ABISP 745ffd83dbSDimitry Andric ABISysV_ppc64::CreateInstance(lldb::ProcessSP process_sp, 755ffd83dbSDimitry Andric const ArchSpec &arch) { 765ffd83dbSDimitry Andric if (arch.GetTriple().isPPC64()) 775ffd83dbSDimitry Andric return ABISP( 785ffd83dbSDimitry Andric new ABISysV_ppc64(std::move(process_sp), MakeMCRegisterInfo(arch))); 795ffd83dbSDimitry Andric return ABISP(); 805ffd83dbSDimitry Andric } 815ffd83dbSDimitry Andric 825ffd83dbSDimitry Andric bool ABISysV_ppc64::PrepareTrivialCall(Thread &thread, addr_t sp, 835ffd83dbSDimitry Andric addr_t func_addr, addr_t return_addr, 845ffd83dbSDimitry Andric llvm::ArrayRef<addr_t> args) const { 8581ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Expressions); 865ffd83dbSDimitry Andric 875ffd83dbSDimitry Andric if (log) { 885ffd83dbSDimitry Andric StreamString s; 895ffd83dbSDimitry Andric s.Printf("ABISysV_ppc64::PrepareTrivialCall (tid = 0x%" PRIx64 905ffd83dbSDimitry Andric ", sp = 0x%" PRIx64 ", func_addr = 0x%" PRIx64 915ffd83dbSDimitry Andric ", return_addr = 0x%" PRIx64, 925ffd83dbSDimitry Andric thread.GetID(), (uint64_t)sp, (uint64_t)func_addr, 935ffd83dbSDimitry Andric (uint64_t)return_addr); 945ffd83dbSDimitry Andric 955ffd83dbSDimitry Andric for (size_t i = 0; i < args.size(); ++i) 965ffd83dbSDimitry Andric s.Printf(", arg%" PRIu64 " = 0x%" PRIx64, static_cast<uint64_t>(i + 1), 975ffd83dbSDimitry Andric args[i]); 985ffd83dbSDimitry Andric s.PutCString(")"); 995ffd83dbSDimitry Andric log->PutString(s.GetString()); 1005ffd83dbSDimitry Andric } 1015ffd83dbSDimitry Andric 1025ffd83dbSDimitry Andric RegisterContext *reg_ctx = thread.GetRegisterContext().get(); 1035ffd83dbSDimitry Andric if (!reg_ctx) 1045ffd83dbSDimitry Andric return false; 1055ffd83dbSDimitry Andric 1065ffd83dbSDimitry Andric const RegisterInfo *reg_info = nullptr; 1075ffd83dbSDimitry Andric 1085ffd83dbSDimitry Andric if (args.size() > 8) // TODO handle more than 8 arguments 1095ffd83dbSDimitry Andric return false; 1105ffd83dbSDimitry Andric 1115ffd83dbSDimitry Andric for (size_t i = 0; i < args.size(); ++i) { 1125ffd83dbSDimitry Andric reg_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric, 1135ffd83dbSDimitry Andric LLDB_REGNUM_GENERIC_ARG1 + i); 1145ffd83dbSDimitry Andric LLDB_LOGF(log, "About to write arg%" PRIu64 " (0x%" PRIx64 ") into %s", 1155ffd83dbSDimitry Andric static_cast<uint64_t>(i + 1), args[i], reg_info->name); 1165ffd83dbSDimitry Andric if (!reg_ctx->WriteRegisterFromUnsigned(reg_info, args[i])) 1175ffd83dbSDimitry Andric return false; 1185ffd83dbSDimitry Andric } 1195ffd83dbSDimitry Andric 1205ffd83dbSDimitry Andric // First, align the SP 1215ffd83dbSDimitry Andric 1225ffd83dbSDimitry Andric LLDB_LOGF(log, "16-byte aligning SP: 0x%" PRIx64 " to 0x%" PRIx64, 1235ffd83dbSDimitry Andric (uint64_t)sp, (uint64_t)(sp & ~0xfull)); 1245ffd83dbSDimitry Andric 1255ffd83dbSDimitry Andric sp &= ~(0xfull); // 16-byte alignment 1265ffd83dbSDimitry Andric 1275ffd83dbSDimitry Andric sp -= 544; // allocate frame to save TOC, RA and SP. 1285ffd83dbSDimitry Andric 1295ffd83dbSDimitry Andric Status error; 1305ffd83dbSDimitry Andric uint64_t reg_value; 1315ffd83dbSDimitry Andric const RegisterInfo *pc_reg_info = 1325ffd83dbSDimitry Andric reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC); 1335ffd83dbSDimitry Andric const RegisterInfo *sp_reg_info = 1345ffd83dbSDimitry Andric reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP); 1355ffd83dbSDimitry Andric ProcessSP process_sp(thread.GetProcess()); 1365ffd83dbSDimitry Andric const RegisterInfo *lr_reg_info = 1375ffd83dbSDimitry Andric reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA); 1385ffd83dbSDimitry Andric const RegisterInfo *r2_reg_info = reg_ctx->GetRegisterInfoAtIndex(2); 1395ffd83dbSDimitry Andric const RegisterInfo *r12_reg_info = reg_ctx->GetRegisterInfoAtIndex(12); 1405ffd83dbSDimitry Andric 1415ffd83dbSDimitry Andric // Save return address onto the stack. 1425ffd83dbSDimitry Andric LLDB_LOGF(log, 1435ffd83dbSDimitry Andric "Pushing the return address onto the stack: 0x%" PRIx64 1445ffd83dbSDimitry Andric "(+16): 0x%" PRIx64, 1455ffd83dbSDimitry Andric (uint64_t)sp, (uint64_t)return_addr); 1465ffd83dbSDimitry Andric if (!process_sp->WritePointerToMemory(sp + 16, return_addr, error)) 1475ffd83dbSDimitry Andric return false; 1485ffd83dbSDimitry Andric 1495ffd83dbSDimitry Andric // Write the return address to link register. 1505ffd83dbSDimitry Andric LLDB_LOGF(log, "Writing LR: 0x%" PRIx64, (uint64_t)return_addr); 1515ffd83dbSDimitry Andric if (!reg_ctx->WriteRegisterFromUnsigned(lr_reg_info, return_addr)) 1525ffd83dbSDimitry Andric return false; 1535ffd83dbSDimitry Andric 1545ffd83dbSDimitry Andric // Write target address to %r12 register. 1555ffd83dbSDimitry Andric LLDB_LOGF(log, "Writing R12: 0x%" PRIx64, (uint64_t)func_addr); 1565ffd83dbSDimitry Andric if (!reg_ctx->WriteRegisterFromUnsigned(r12_reg_info, func_addr)) 1575ffd83dbSDimitry Andric return false; 1585ffd83dbSDimitry Andric 1595ffd83dbSDimitry Andric // Read TOC pointer value. 1605ffd83dbSDimitry Andric reg_value = reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0); 1615ffd83dbSDimitry Andric 1625ffd83dbSDimitry Andric // Write TOC pointer onto the stack. 1635ffd83dbSDimitry Andric uint64_t stack_offset; 1645ffd83dbSDimitry Andric if (GetByteOrder() == lldb::eByteOrderLittle) 1655ffd83dbSDimitry Andric stack_offset = 24; 1665ffd83dbSDimitry Andric else 1675ffd83dbSDimitry Andric stack_offset = 40; 1685ffd83dbSDimitry Andric 1695ffd83dbSDimitry Andric LLDB_LOGF(log, "Writing R2 (TOC) at SP(0x%" PRIx64 ")+%d: 0x%" PRIx64, 1705ffd83dbSDimitry Andric (uint64_t)(sp + stack_offset), (int)stack_offset, 1715ffd83dbSDimitry Andric (uint64_t)reg_value); 1725ffd83dbSDimitry Andric if (!process_sp->WritePointerToMemory(sp + stack_offset, reg_value, error)) 1735ffd83dbSDimitry Andric return false; 1745ffd83dbSDimitry Andric 1755ffd83dbSDimitry Andric // Read the current SP value. 1765ffd83dbSDimitry Andric reg_value = reg_ctx->ReadRegisterAsUnsigned(sp_reg_info, 0); 1775ffd83dbSDimitry Andric 1785ffd83dbSDimitry Andric // Save current SP onto the stack. 1795ffd83dbSDimitry Andric LLDB_LOGF(log, "Writing SP at SP(0x%" PRIx64 ")+0: 0x%" PRIx64, (uint64_t)sp, 1805ffd83dbSDimitry Andric (uint64_t)reg_value); 1815ffd83dbSDimitry Andric if (!process_sp->WritePointerToMemory(sp, reg_value, error)) 1825ffd83dbSDimitry Andric return false; 1835ffd83dbSDimitry Andric 1845ffd83dbSDimitry Andric // %r1 is set to the actual stack value. 1855ffd83dbSDimitry Andric LLDB_LOGF(log, "Writing SP: 0x%" PRIx64, (uint64_t)sp); 1865ffd83dbSDimitry Andric 1875ffd83dbSDimitry Andric if (!reg_ctx->WriteRegisterFromUnsigned(sp_reg_info, sp)) 1885ffd83dbSDimitry Andric return false; 1895ffd83dbSDimitry Andric 1905ffd83dbSDimitry Andric // %pc is set to the address of the called function. 1915ffd83dbSDimitry Andric 1925ffd83dbSDimitry Andric LLDB_LOGF(log, "Writing IP: 0x%" PRIx64, (uint64_t)func_addr); 1935ffd83dbSDimitry Andric 1945ffd83dbSDimitry Andric if (!reg_ctx->WriteRegisterFromUnsigned(pc_reg_info, func_addr)) 1955ffd83dbSDimitry Andric return false; 1965ffd83dbSDimitry Andric 1975ffd83dbSDimitry Andric return true; 1985ffd83dbSDimitry Andric } 1995ffd83dbSDimitry Andric 2005ffd83dbSDimitry Andric static bool ReadIntegerArgument(Scalar &scalar, unsigned int bit_width, 2015ffd83dbSDimitry Andric bool is_signed, Thread &thread, 2025ffd83dbSDimitry Andric uint32_t *argument_register_ids, 2035ffd83dbSDimitry Andric unsigned int ¤t_argument_register, 2045ffd83dbSDimitry Andric addr_t ¤t_stack_argument) { 2055ffd83dbSDimitry Andric if (bit_width > 64) 2065ffd83dbSDimitry Andric return false; // Scalar can't hold large integer arguments 2075ffd83dbSDimitry Andric 2085ffd83dbSDimitry Andric if (current_argument_register < 6) { 2095ffd83dbSDimitry Andric scalar = thread.GetRegisterContext()->ReadRegisterAsUnsigned( 2105ffd83dbSDimitry Andric argument_register_ids[current_argument_register], 0); 2115ffd83dbSDimitry Andric current_argument_register++; 2125ffd83dbSDimitry Andric if (is_signed) 2135ffd83dbSDimitry Andric scalar.SignExtend(bit_width); 2145ffd83dbSDimitry Andric } else { 2155ffd83dbSDimitry Andric uint32_t byte_size = (bit_width + (8 - 1)) / 8; 2165ffd83dbSDimitry Andric Status error; 2175ffd83dbSDimitry Andric if (thread.GetProcess()->ReadScalarIntegerFromMemory( 2185ffd83dbSDimitry Andric current_stack_argument, byte_size, is_signed, scalar, error)) { 2195ffd83dbSDimitry Andric current_stack_argument += byte_size; 2205ffd83dbSDimitry Andric return true; 2215ffd83dbSDimitry Andric } 2225ffd83dbSDimitry Andric return false; 2235ffd83dbSDimitry Andric } 2245ffd83dbSDimitry Andric return true; 2255ffd83dbSDimitry Andric } 2265ffd83dbSDimitry Andric 2275ffd83dbSDimitry Andric bool ABISysV_ppc64::GetArgumentValues(Thread &thread, ValueList &values) const { 2285ffd83dbSDimitry Andric unsigned int num_values = values.GetSize(); 2295ffd83dbSDimitry Andric unsigned int value_index; 2305ffd83dbSDimitry Andric 2315ffd83dbSDimitry Andric // Extract the register context so we can read arguments from registers 2325ffd83dbSDimitry Andric 2335ffd83dbSDimitry Andric RegisterContext *reg_ctx = thread.GetRegisterContext().get(); 2345ffd83dbSDimitry Andric 2355ffd83dbSDimitry Andric if (!reg_ctx) 2365ffd83dbSDimitry Andric return false; 2375ffd83dbSDimitry Andric 2385ffd83dbSDimitry Andric // Get the pointer to the first stack argument so we have a place to start 2395ffd83dbSDimitry Andric // when reading data 2405ffd83dbSDimitry Andric 2415ffd83dbSDimitry Andric addr_t sp = reg_ctx->GetSP(0); 2425ffd83dbSDimitry Andric 2435ffd83dbSDimitry Andric if (!sp) 2445ffd83dbSDimitry Andric return false; 2455ffd83dbSDimitry Andric 2465ffd83dbSDimitry Andric uint64_t stack_offset; 2475ffd83dbSDimitry Andric if (GetByteOrder() == lldb::eByteOrderLittle) 2485ffd83dbSDimitry Andric stack_offset = 32; 2495ffd83dbSDimitry Andric else 2505ffd83dbSDimitry Andric stack_offset = 48; 2515ffd83dbSDimitry Andric 2525ffd83dbSDimitry Andric // jump over return address. 2535ffd83dbSDimitry Andric addr_t current_stack_argument = sp + stack_offset; 2545ffd83dbSDimitry Andric uint32_t argument_register_ids[8]; 2555ffd83dbSDimitry Andric 2565ffd83dbSDimitry Andric for (size_t i = 0; i < 8; ++i) { 2575ffd83dbSDimitry Andric argument_register_ids[i] = 2585ffd83dbSDimitry Andric reg_ctx 2595ffd83dbSDimitry Andric ->GetRegisterInfo(eRegisterKindGeneric, 2605ffd83dbSDimitry Andric LLDB_REGNUM_GENERIC_ARG1 + i) 2615ffd83dbSDimitry Andric ->kinds[eRegisterKindLLDB]; 2625ffd83dbSDimitry Andric } 2635ffd83dbSDimitry Andric 2645ffd83dbSDimitry Andric unsigned int current_argument_register = 0; 2655ffd83dbSDimitry Andric 2665ffd83dbSDimitry Andric for (value_index = 0; value_index < num_values; ++value_index) { 2675ffd83dbSDimitry Andric Value *value = values.GetValueAtIndex(value_index); 2685ffd83dbSDimitry Andric 2695ffd83dbSDimitry Andric if (!value) 2705ffd83dbSDimitry Andric return false; 2715ffd83dbSDimitry Andric 2725ffd83dbSDimitry Andric // We currently only support extracting values with Clang QualTypes. Do we 2735ffd83dbSDimitry Andric // care about others? 2745ffd83dbSDimitry Andric CompilerType compiler_type = value->GetCompilerType(); 275bdd1243dSDimitry Andric std::optional<uint64_t> bit_size = compiler_type.GetBitSize(&thread); 2765ffd83dbSDimitry Andric if (!bit_size) 2775ffd83dbSDimitry Andric return false; 2785ffd83dbSDimitry Andric bool is_signed; 2795ffd83dbSDimitry Andric 2805ffd83dbSDimitry Andric if (compiler_type.IsIntegerOrEnumerationType(is_signed)) { 2815ffd83dbSDimitry Andric ReadIntegerArgument(value->GetScalar(), *bit_size, is_signed, thread, 2825ffd83dbSDimitry Andric argument_register_ids, current_argument_register, 2835ffd83dbSDimitry Andric current_stack_argument); 2845ffd83dbSDimitry Andric } else if (compiler_type.IsPointerType()) { 2855ffd83dbSDimitry Andric ReadIntegerArgument(value->GetScalar(), *bit_size, false, thread, 2865ffd83dbSDimitry Andric argument_register_ids, current_argument_register, 2875ffd83dbSDimitry Andric current_stack_argument); 2885ffd83dbSDimitry Andric } 2895ffd83dbSDimitry Andric } 2905ffd83dbSDimitry Andric 2915ffd83dbSDimitry Andric return true; 2925ffd83dbSDimitry Andric } 2935ffd83dbSDimitry Andric 2945ffd83dbSDimitry Andric Status ABISysV_ppc64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, 2955ffd83dbSDimitry Andric lldb::ValueObjectSP &new_value_sp) { 2965ffd83dbSDimitry Andric Status error; 2975ffd83dbSDimitry Andric if (!new_value_sp) { 2985ffd83dbSDimitry Andric error.SetErrorString("Empty value object for return value."); 2995ffd83dbSDimitry Andric return error; 3005ffd83dbSDimitry Andric } 3015ffd83dbSDimitry Andric 3025ffd83dbSDimitry Andric CompilerType compiler_type = new_value_sp->GetCompilerType(); 3035ffd83dbSDimitry Andric if (!compiler_type) { 3045ffd83dbSDimitry Andric error.SetErrorString("Null clang type for return value."); 3055ffd83dbSDimitry Andric return error; 3065ffd83dbSDimitry Andric } 3075ffd83dbSDimitry Andric 3085ffd83dbSDimitry Andric Thread *thread = frame_sp->GetThread().get(); 3095ffd83dbSDimitry Andric 3105ffd83dbSDimitry Andric bool is_signed; 3115ffd83dbSDimitry Andric uint32_t count; 3125ffd83dbSDimitry Andric bool is_complex; 3135ffd83dbSDimitry Andric 3145ffd83dbSDimitry Andric RegisterContext *reg_ctx = thread->GetRegisterContext().get(); 3155ffd83dbSDimitry Andric 3165ffd83dbSDimitry Andric bool set_it_simple = false; 3175ffd83dbSDimitry Andric if (compiler_type.IsIntegerOrEnumerationType(is_signed) || 3185ffd83dbSDimitry Andric compiler_type.IsPointerType()) { 3195ffd83dbSDimitry Andric const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName("r3", 0); 3205ffd83dbSDimitry Andric 3215ffd83dbSDimitry Andric DataExtractor data; 3225ffd83dbSDimitry Andric Status data_error; 3235ffd83dbSDimitry Andric size_t num_bytes = new_value_sp->GetData(data, data_error); 3245ffd83dbSDimitry Andric if (data_error.Fail()) { 3255ffd83dbSDimitry Andric error.SetErrorStringWithFormat( 3265ffd83dbSDimitry Andric "Couldn't convert return value to raw data: %s", 3275ffd83dbSDimitry Andric data_error.AsCString()); 3285ffd83dbSDimitry Andric return error; 3295ffd83dbSDimitry Andric } 3305ffd83dbSDimitry Andric lldb::offset_t offset = 0; 3315ffd83dbSDimitry Andric if (num_bytes <= 8) { 3325ffd83dbSDimitry Andric uint64_t raw_value = data.GetMaxU64(&offset, num_bytes); 3335ffd83dbSDimitry Andric 3345ffd83dbSDimitry Andric if (reg_ctx->WriteRegisterFromUnsigned(reg_info, raw_value)) 3355ffd83dbSDimitry Andric set_it_simple = true; 3365ffd83dbSDimitry Andric } else { 3375ffd83dbSDimitry Andric error.SetErrorString("We don't support returning longer than 64 bit " 3385ffd83dbSDimitry Andric "integer values at present."); 3395ffd83dbSDimitry Andric } 3405ffd83dbSDimitry Andric } else if (compiler_type.IsFloatingPointType(count, is_complex)) { 3415ffd83dbSDimitry Andric if (is_complex) 3425ffd83dbSDimitry Andric error.SetErrorString( 3435ffd83dbSDimitry Andric "We don't support returning complex values at present"); 3445ffd83dbSDimitry Andric else { 345bdd1243dSDimitry Andric std::optional<uint64_t> bit_width = 3465ffd83dbSDimitry Andric compiler_type.GetBitSize(frame_sp.get()); 3475ffd83dbSDimitry Andric if (!bit_width) { 3485ffd83dbSDimitry Andric error.SetErrorString("can't get size of type"); 3495ffd83dbSDimitry Andric return error; 3505ffd83dbSDimitry Andric } 3515ffd83dbSDimitry Andric if (*bit_width <= 64) { 3525ffd83dbSDimitry Andric DataExtractor data; 3535ffd83dbSDimitry Andric Status data_error; 3545ffd83dbSDimitry Andric size_t num_bytes = new_value_sp->GetData(data, data_error); 3555ffd83dbSDimitry Andric if (data_error.Fail()) { 3565ffd83dbSDimitry Andric error.SetErrorStringWithFormat( 3575ffd83dbSDimitry Andric "Couldn't convert return value to raw data: %s", 3585ffd83dbSDimitry Andric data_error.AsCString()); 3595ffd83dbSDimitry Andric return error; 3605ffd83dbSDimitry Andric } 3615ffd83dbSDimitry Andric 3625ffd83dbSDimitry Andric unsigned char buffer[16]; 3635ffd83dbSDimitry Andric ByteOrder byte_order = data.GetByteOrder(); 3645ffd83dbSDimitry Andric 3655ffd83dbSDimitry Andric data.CopyByteOrderedData(0, num_bytes, buffer, 16, byte_order); 3665ffd83dbSDimitry Andric set_it_simple = true; 3675ffd83dbSDimitry Andric } else { 3685ffd83dbSDimitry Andric // FIXME - don't know how to do 80 bit long doubles yet. 3695ffd83dbSDimitry Andric error.SetErrorString( 3705ffd83dbSDimitry Andric "We don't support returning float values > 64 bits at present"); 3715ffd83dbSDimitry Andric } 3725ffd83dbSDimitry Andric } 3735ffd83dbSDimitry Andric } 3745ffd83dbSDimitry Andric 3755ffd83dbSDimitry Andric if (!set_it_simple) { 3765ffd83dbSDimitry Andric // Okay we've got a structure or something that doesn't fit in a simple 3775ffd83dbSDimitry Andric // register. We should figure out where it really goes, but we don't 3785ffd83dbSDimitry Andric // support this yet. 3795ffd83dbSDimitry Andric error.SetErrorString("We only support setting simple integer and float " 3805ffd83dbSDimitry Andric "return types at present."); 3815ffd83dbSDimitry Andric } 3825ffd83dbSDimitry Andric 3835ffd83dbSDimitry Andric return error; 3845ffd83dbSDimitry Andric } 3855ffd83dbSDimitry Andric 3865ffd83dbSDimitry Andric // 3875ffd83dbSDimitry Andric // ReturnValueExtractor 3885ffd83dbSDimitry Andric // 3895ffd83dbSDimitry Andric 3905ffd83dbSDimitry Andric namespace { 3915ffd83dbSDimitry Andric 3925ffd83dbSDimitry Andric #define LOG_PREFIX "ReturnValueExtractor: " 3935ffd83dbSDimitry Andric 3945ffd83dbSDimitry Andric class ReturnValueExtractor { 3955ffd83dbSDimitry Andric // This class represents a register, from which data may be extracted. 3965ffd83dbSDimitry Andric // 3975ffd83dbSDimitry Andric // It may be constructed by directly specifying its index (where 0 is the 3985ffd83dbSDimitry Andric // first register used to return values) or by specifying the offset of a 3995ffd83dbSDimitry Andric // given struct field, in which case the appropriated register index will be 4005ffd83dbSDimitry Andric // calculated. 4015ffd83dbSDimitry Andric class Register { 4025ffd83dbSDimitry Andric public: 4035ffd83dbSDimitry Andric enum Type { 4045ffd83dbSDimitry Andric GPR, // General Purpose Register 4055ffd83dbSDimitry Andric FPR // Floating Point Register 4065ffd83dbSDimitry Andric }; 4075ffd83dbSDimitry Andric 4085ffd83dbSDimitry Andric // main constructor 4095ffd83dbSDimitry Andric // 4105ffd83dbSDimitry Andric // offs - field offset in struct 4115ffd83dbSDimitry Andric Register(Type ty, uint32_t index, uint32_t offs, RegisterContext *reg_ctx, 4125ffd83dbSDimitry Andric ByteOrder byte_order) 4135ffd83dbSDimitry Andric : m_index(index), m_offs(offs % sizeof(uint64_t)), 4145ffd83dbSDimitry Andric m_avail(sizeof(uint64_t) - m_offs), m_type(ty), m_reg_ctx(reg_ctx), 4155ffd83dbSDimitry Andric m_byte_order(byte_order) {} 4165ffd83dbSDimitry Andric 4175ffd83dbSDimitry Andric // explicit index, no offset 4185ffd83dbSDimitry Andric Register(Type ty, uint32_t index, RegisterContext *reg_ctx, 4195ffd83dbSDimitry Andric ByteOrder byte_order) 4205ffd83dbSDimitry Andric : Register(ty, index, 0, reg_ctx, byte_order) {} 4215ffd83dbSDimitry Andric 4225ffd83dbSDimitry Andric // GPR, calculate index from offs 4235ffd83dbSDimitry Andric Register(uint32_t offs, RegisterContext *reg_ctx, ByteOrder byte_order) 4245ffd83dbSDimitry Andric : Register(GPR, offs / sizeof(uint64_t), offs, reg_ctx, byte_order) {} 4255ffd83dbSDimitry Andric 4265ffd83dbSDimitry Andric uint32_t Index() const { return m_index; } 4275ffd83dbSDimitry Andric 4285ffd83dbSDimitry Andric // register offset where data is located 4295ffd83dbSDimitry Andric uint32_t Offs() const { return m_offs; } 4305ffd83dbSDimitry Andric 4315ffd83dbSDimitry Andric // available bytes in this register 4325ffd83dbSDimitry Andric uint32_t Avail() const { return m_avail; } 4335ffd83dbSDimitry Andric 4345ffd83dbSDimitry Andric bool IsValid() const { 4355ffd83dbSDimitry Andric if (m_index > 7) { 4365ffd83dbSDimitry Andric LLDB_LOG(m_log, LOG_PREFIX 4375ffd83dbSDimitry Andric "No more than 8 registers should be used to return values"); 4385ffd83dbSDimitry Andric return false; 4395ffd83dbSDimitry Andric } 4405ffd83dbSDimitry Andric return true; 4415ffd83dbSDimitry Andric } 4425ffd83dbSDimitry Andric 4435ffd83dbSDimitry Andric std::string GetName() const { 4445ffd83dbSDimitry Andric if (m_type == GPR) 4455ffd83dbSDimitry Andric return ("r" + llvm::Twine(m_index + 3)).str(); 4465ffd83dbSDimitry Andric else 4475ffd83dbSDimitry Andric return ("f" + llvm::Twine(m_index + 1)).str(); 4485ffd83dbSDimitry Andric } 4495ffd83dbSDimitry Andric 4505ffd83dbSDimitry Andric // get raw register data 4515ffd83dbSDimitry Andric bool GetRawData(uint64_t &raw_data) { 4525ffd83dbSDimitry Andric const RegisterInfo *reg_info = 4535ffd83dbSDimitry Andric m_reg_ctx->GetRegisterInfoByName(GetName()); 4545ffd83dbSDimitry Andric if (!reg_info) { 4555ffd83dbSDimitry Andric LLDB_LOG(m_log, LOG_PREFIX "Failed to get RegisterInfo"); 4565ffd83dbSDimitry Andric return false; 4575ffd83dbSDimitry Andric } 4585ffd83dbSDimitry Andric 4595ffd83dbSDimitry Andric RegisterValue reg_val; 4605ffd83dbSDimitry Andric if (!m_reg_ctx->ReadRegister(reg_info, reg_val)) { 4615ffd83dbSDimitry Andric LLDB_LOG(m_log, LOG_PREFIX "ReadRegister() failed"); 4625ffd83dbSDimitry Andric return false; 4635ffd83dbSDimitry Andric } 4645ffd83dbSDimitry Andric 4655ffd83dbSDimitry Andric Status error; 4665ffd83dbSDimitry Andric uint32_t rc = reg_val.GetAsMemoryData( 467bdd1243dSDimitry Andric *reg_info, &raw_data, sizeof(raw_data), m_byte_order, error); 4685ffd83dbSDimitry Andric if (rc != sizeof(raw_data)) { 4695ffd83dbSDimitry Andric LLDB_LOG(m_log, LOG_PREFIX "GetAsMemoryData() failed"); 4705ffd83dbSDimitry Andric return false; 4715ffd83dbSDimitry Andric } 4725ffd83dbSDimitry Andric 4735ffd83dbSDimitry Andric return true; 4745ffd83dbSDimitry Andric } 4755ffd83dbSDimitry Andric 4765ffd83dbSDimitry Andric private: 4775ffd83dbSDimitry Andric uint32_t m_index; 4785ffd83dbSDimitry Andric uint32_t m_offs; 4795ffd83dbSDimitry Andric uint32_t m_avail; 4805ffd83dbSDimitry Andric Type m_type; 4815ffd83dbSDimitry Andric RegisterContext *m_reg_ctx; 4825ffd83dbSDimitry Andric ByteOrder m_byte_order; 48381ad6265SDimitry Andric Log *m_log = GetLog(LLDBLog::Expressions); 4845ffd83dbSDimitry Andric }; 4855ffd83dbSDimitry Andric 4865ffd83dbSDimitry Andric Register GetGPR(uint32_t index) const { 4875ffd83dbSDimitry Andric return Register(Register::GPR, index, m_reg_ctx, m_byte_order); 4885ffd83dbSDimitry Andric } 4895ffd83dbSDimitry Andric 4905ffd83dbSDimitry Andric Register GetFPR(uint32_t index) const { 4915ffd83dbSDimitry Andric return Register(Register::FPR, index, m_reg_ctx, m_byte_order); 4925ffd83dbSDimitry Andric } 4935ffd83dbSDimitry Andric 4945ffd83dbSDimitry Andric Register GetGPRByOffs(uint32_t offs) const { 4955ffd83dbSDimitry Andric return Register(offs, m_reg_ctx, m_byte_order); 4965ffd83dbSDimitry Andric } 4975ffd83dbSDimitry Andric 4985ffd83dbSDimitry Andric public: 4995ffd83dbSDimitry Andric // factory 5005ffd83dbSDimitry Andric static llvm::Expected<ReturnValueExtractor> Create(Thread &thread, 5015ffd83dbSDimitry Andric CompilerType &type) { 5025ffd83dbSDimitry Andric RegisterContext *reg_ctx = thread.GetRegisterContext().get(); 5035ffd83dbSDimitry Andric if (!reg_ctx) 504*0fca6ea1SDimitry Andric return llvm::createStringError(LOG_PREFIX 505*0fca6ea1SDimitry Andric "Failed to get RegisterContext"); 5065ffd83dbSDimitry Andric 5075ffd83dbSDimitry Andric ProcessSP process_sp = thread.GetProcess(); 5085ffd83dbSDimitry Andric if (!process_sp) 509*0fca6ea1SDimitry Andric return llvm::createStringError(LOG_PREFIX "GetProcess() failed"); 5105ffd83dbSDimitry Andric 5115ffd83dbSDimitry Andric return ReturnValueExtractor(thread, type, reg_ctx, process_sp); 5125ffd83dbSDimitry Andric } 5135ffd83dbSDimitry Andric 5145ffd83dbSDimitry Andric // main method: get value of the type specified at construction time 5155ffd83dbSDimitry Andric ValueObjectSP GetValue() { 5165ffd83dbSDimitry Andric const uint32_t type_flags = m_type.GetTypeInfo(); 5175ffd83dbSDimitry Andric 5185ffd83dbSDimitry Andric // call the appropriate type handler 5195ffd83dbSDimitry Andric ValueSP value_sp; 5205ffd83dbSDimitry Andric ValueObjectSP valobj_sp; 5215ffd83dbSDimitry Andric if (type_flags & eTypeIsScalar) { 5225ffd83dbSDimitry Andric if (type_flags & eTypeIsInteger) { 5235ffd83dbSDimitry Andric value_sp = GetIntegerValue(0); 5245ffd83dbSDimitry Andric } else if (type_flags & eTypeIsFloat) { 5255ffd83dbSDimitry Andric if (type_flags & eTypeIsComplex) { 5265ffd83dbSDimitry Andric LLDB_LOG(m_log, LOG_PREFIX "Complex numbers are not supported yet"); 5275ffd83dbSDimitry Andric return ValueObjectSP(); 5285ffd83dbSDimitry Andric } else { 5295ffd83dbSDimitry Andric value_sp = GetFloatValue(m_type, 0); 5305ffd83dbSDimitry Andric } 5315ffd83dbSDimitry Andric } 5325ffd83dbSDimitry Andric } else if (type_flags & eTypeIsPointer) { 5335ffd83dbSDimitry Andric value_sp = GetPointerValue(0); 5345ffd83dbSDimitry Andric } 5355ffd83dbSDimitry Andric 5365ffd83dbSDimitry Andric if (value_sp) { 5375ffd83dbSDimitry Andric valobj_sp = ValueObjectConstResult::Create( 5385ffd83dbSDimitry Andric m_thread.GetStackFrameAtIndex(0).get(), *value_sp, ConstString("")); 5395ffd83dbSDimitry Andric } else if (type_flags & eTypeIsVector) { 5405ffd83dbSDimitry Andric valobj_sp = GetVectorValueObject(); 5415ffd83dbSDimitry Andric } else if (type_flags & eTypeIsStructUnion || type_flags & eTypeIsClass) { 5425ffd83dbSDimitry Andric valobj_sp = GetStructValueObject(); 5435ffd83dbSDimitry Andric } 5445ffd83dbSDimitry Andric 5455ffd83dbSDimitry Andric return valobj_sp; 5465ffd83dbSDimitry Andric } 5475ffd83dbSDimitry Andric 5485ffd83dbSDimitry Andric private: 5495ffd83dbSDimitry Andric // data 5505ffd83dbSDimitry Andric Thread &m_thread; 5515ffd83dbSDimitry Andric CompilerType &m_type; 5525ffd83dbSDimitry Andric uint64_t m_byte_size; 5535ffd83dbSDimitry Andric std::unique_ptr<DataBufferHeap> m_data_up; 5545ffd83dbSDimitry Andric int32_t m_src_offs = 0; 5555ffd83dbSDimitry Andric int32_t m_dst_offs = 0; 5565ffd83dbSDimitry Andric bool m_packed = false; 55781ad6265SDimitry Andric Log *m_log = GetLog(LLDBLog::Expressions); 5585ffd83dbSDimitry Andric RegisterContext *m_reg_ctx; 5595ffd83dbSDimitry Andric ProcessSP m_process_sp; 5605ffd83dbSDimitry Andric ByteOrder m_byte_order; 5615ffd83dbSDimitry Andric uint32_t m_addr_size; 5625ffd83dbSDimitry Andric 5635ffd83dbSDimitry Andric // methods 5645ffd83dbSDimitry Andric 5655ffd83dbSDimitry Andric // constructor 5665ffd83dbSDimitry Andric ReturnValueExtractor(Thread &thread, CompilerType &type, 5675ffd83dbSDimitry Andric RegisterContext *reg_ctx, ProcessSP process_sp) 5685ffd83dbSDimitry Andric : m_thread(thread), m_type(type), 56981ad6265SDimitry Andric m_byte_size(m_type.GetByteSize(&thread).value_or(0)), 5705ffd83dbSDimitry Andric m_data_up(new DataBufferHeap(m_byte_size, 0)), m_reg_ctx(reg_ctx), 5715ffd83dbSDimitry Andric m_process_sp(process_sp), m_byte_order(process_sp->GetByteOrder()), 5725ffd83dbSDimitry Andric m_addr_size( 5735ffd83dbSDimitry Andric process_sp->GetTarget().GetArchitecture().GetAddressByteSize()) {} 5745ffd83dbSDimitry Andric 5755ffd83dbSDimitry Andric // build a new scalar value 5765ffd83dbSDimitry Andric ValueSP NewScalarValue(CompilerType &type) { 5775ffd83dbSDimitry Andric ValueSP value_sp(new Value); 5785ffd83dbSDimitry Andric value_sp->SetCompilerType(type); 579fe6060f1SDimitry Andric value_sp->SetValueType(Value::ValueType::Scalar); 5805ffd83dbSDimitry Andric return value_sp; 5815ffd83dbSDimitry Andric } 5825ffd83dbSDimitry Andric 5835ffd83dbSDimitry Andric // get an integer value in the specified register 5845ffd83dbSDimitry Andric ValueSP GetIntegerValue(uint32_t reg_index) { 5855ffd83dbSDimitry Andric uint64_t raw_value; 5865ffd83dbSDimitry Andric auto reg = GetGPR(reg_index); 5875ffd83dbSDimitry Andric if (!reg.GetRawData(raw_value)) 5885ffd83dbSDimitry Andric return ValueSP(); 5895ffd83dbSDimitry Andric 5905ffd83dbSDimitry Andric // build value from data 5915ffd83dbSDimitry Andric ValueSP value_sp(NewScalarValue(m_type)); 5925ffd83dbSDimitry Andric 5935ffd83dbSDimitry Andric uint32_t type_flags = m_type.GetTypeInfo(); 5945ffd83dbSDimitry Andric bool is_signed = (type_flags & eTypeIsSigned) != 0; 5955ffd83dbSDimitry Andric 5965ffd83dbSDimitry Andric switch (m_byte_size) { 5975ffd83dbSDimitry Andric case sizeof(uint64_t): 5985ffd83dbSDimitry Andric if (is_signed) 5995ffd83dbSDimitry Andric value_sp->GetScalar() = (int64_t)(raw_value); 6005ffd83dbSDimitry Andric else 6015ffd83dbSDimitry Andric value_sp->GetScalar() = (uint64_t)(raw_value); 6025ffd83dbSDimitry Andric break; 6035ffd83dbSDimitry Andric 6045ffd83dbSDimitry Andric case sizeof(uint32_t): 6055ffd83dbSDimitry Andric if (is_signed) 6065ffd83dbSDimitry Andric value_sp->GetScalar() = (int32_t)(raw_value & UINT32_MAX); 6075ffd83dbSDimitry Andric else 6085ffd83dbSDimitry Andric value_sp->GetScalar() = (uint32_t)(raw_value & UINT32_MAX); 6095ffd83dbSDimitry Andric break; 6105ffd83dbSDimitry Andric 6115ffd83dbSDimitry Andric case sizeof(uint16_t): 6125ffd83dbSDimitry Andric if (is_signed) 6135ffd83dbSDimitry Andric value_sp->GetScalar() = (int16_t)(raw_value & UINT16_MAX); 6145ffd83dbSDimitry Andric else 6155ffd83dbSDimitry Andric value_sp->GetScalar() = (uint16_t)(raw_value & UINT16_MAX); 6165ffd83dbSDimitry Andric break; 6175ffd83dbSDimitry Andric 6185ffd83dbSDimitry Andric case sizeof(uint8_t): 6195ffd83dbSDimitry Andric if (is_signed) 6205ffd83dbSDimitry Andric value_sp->GetScalar() = (int8_t)(raw_value & UINT8_MAX); 6215ffd83dbSDimitry Andric else 6225ffd83dbSDimitry Andric value_sp->GetScalar() = (uint8_t)(raw_value & UINT8_MAX); 6235ffd83dbSDimitry Andric break; 6245ffd83dbSDimitry Andric 6255ffd83dbSDimitry Andric default: 6265ffd83dbSDimitry Andric llvm_unreachable("Invalid integer size"); 6275ffd83dbSDimitry Andric } 6285ffd83dbSDimitry Andric 6295ffd83dbSDimitry Andric return value_sp; 6305ffd83dbSDimitry Andric } 6315ffd83dbSDimitry Andric 6325ffd83dbSDimitry Andric // get a floating point value on the specified register 6335ffd83dbSDimitry Andric ValueSP GetFloatValue(CompilerType &type, uint32_t reg_index) { 6345ffd83dbSDimitry Andric uint64_t raw_data; 6355ffd83dbSDimitry Andric auto reg = GetFPR(reg_index); 6365ffd83dbSDimitry Andric if (!reg.GetRawData(raw_data)) 6375ffd83dbSDimitry Andric return {}; 6385ffd83dbSDimitry Andric 6395ffd83dbSDimitry Andric // build value from data 6405ffd83dbSDimitry Andric ValueSP value_sp(NewScalarValue(type)); 6415ffd83dbSDimitry Andric 6425ffd83dbSDimitry Andric DataExtractor de(&raw_data, sizeof(raw_data), m_byte_order, m_addr_size); 6435ffd83dbSDimitry Andric 6445ffd83dbSDimitry Andric offset_t offset = 0; 645bdd1243dSDimitry Andric std::optional<uint64_t> byte_size = type.GetByteSize(m_process_sp.get()); 6465ffd83dbSDimitry Andric if (!byte_size) 6475ffd83dbSDimitry Andric return {}; 6485ffd83dbSDimitry Andric switch (*byte_size) { 6495ffd83dbSDimitry Andric case sizeof(float): 6505ffd83dbSDimitry Andric value_sp->GetScalar() = (float)de.GetDouble(&offset); 6515ffd83dbSDimitry Andric break; 6525ffd83dbSDimitry Andric 6535ffd83dbSDimitry Andric case sizeof(double): 6545ffd83dbSDimitry Andric value_sp->GetScalar() = de.GetDouble(&offset); 6555ffd83dbSDimitry Andric break; 6565ffd83dbSDimitry Andric 6575ffd83dbSDimitry Andric default: 6585ffd83dbSDimitry Andric llvm_unreachable("Invalid floating point size"); 6595ffd83dbSDimitry Andric } 6605ffd83dbSDimitry Andric 6615ffd83dbSDimitry Andric return value_sp; 6625ffd83dbSDimitry Andric } 6635ffd83dbSDimitry Andric 6645ffd83dbSDimitry Andric // get pointer value from register 6655ffd83dbSDimitry Andric ValueSP GetPointerValue(uint32_t reg_index) { 6665ffd83dbSDimitry Andric uint64_t raw_data; 6675ffd83dbSDimitry Andric auto reg = GetGPR(reg_index); 6685ffd83dbSDimitry Andric if (!reg.GetRawData(raw_data)) 6695ffd83dbSDimitry Andric return ValueSP(); 6705ffd83dbSDimitry Andric 6715ffd83dbSDimitry Andric // build value from raw data 6725ffd83dbSDimitry Andric ValueSP value_sp(NewScalarValue(m_type)); 6735ffd83dbSDimitry Andric value_sp->GetScalar() = raw_data; 6745ffd83dbSDimitry Andric return value_sp; 6755ffd83dbSDimitry Andric } 6765ffd83dbSDimitry Andric 6775ffd83dbSDimitry Andric // build the ValueObject from our data buffer 6785ffd83dbSDimitry Andric ValueObjectSP BuildValueObject() { 6795ffd83dbSDimitry Andric DataExtractor de(DataBufferSP(m_data_up.release()), m_byte_order, 6805ffd83dbSDimitry Andric m_addr_size); 6815ffd83dbSDimitry Andric return ValueObjectConstResult::Create(&m_thread, m_type, ConstString(""), 6825ffd83dbSDimitry Andric de); 6835ffd83dbSDimitry Andric } 6845ffd83dbSDimitry Andric 6855ffd83dbSDimitry Andric // get a vector return value 6865ffd83dbSDimitry Andric ValueObjectSP GetVectorValueObject() { 6875ffd83dbSDimitry Andric const uint32_t MAX_VRS = 2; 6885ffd83dbSDimitry Andric 6895ffd83dbSDimitry Andric // get first V register used to return values 6905ffd83dbSDimitry Andric const RegisterInfo *vr[MAX_VRS]; 6915ffd83dbSDimitry Andric vr[0] = m_reg_ctx->GetRegisterInfoByName("vr2"); 6925ffd83dbSDimitry Andric if (!vr[0]) { 6935ffd83dbSDimitry Andric LLDB_LOG(m_log, LOG_PREFIX "Failed to get vr2 RegisterInfo"); 6945ffd83dbSDimitry Andric return ValueObjectSP(); 6955ffd83dbSDimitry Andric } 6965ffd83dbSDimitry Andric 6975ffd83dbSDimitry Andric const uint32_t vr_size = vr[0]->byte_size; 6985ffd83dbSDimitry Andric size_t vrs = 1; 6995ffd83dbSDimitry Andric if (m_byte_size > 2 * vr_size) { 7005ffd83dbSDimitry Andric LLDB_LOG( 7015ffd83dbSDimitry Andric m_log, LOG_PREFIX 7025ffd83dbSDimitry Andric "Returning vectors that don't fit in 2 VR regs is not supported"); 7035ffd83dbSDimitry Andric return ValueObjectSP(); 7045ffd83dbSDimitry Andric } 7055ffd83dbSDimitry Andric 7065ffd83dbSDimitry Andric // load vr3, if needed 7075ffd83dbSDimitry Andric if (m_byte_size > vr_size) { 7085ffd83dbSDimitry Andric vrs++; 7095ffd83dbSDimitry Andric vr[1] = m_reg_ctx->GetRegisterInfoByName("vr3"); 7105ffd83dbSDimitry Andric if (!vr[1]) { 7115ffd83dbSDimitry Andric LLDB_LOG(m_log, LOG_PREFIX "Failed to get vr3 RegisterInfo"); 7125ffd83dbSDimitry Andric return ValueObjectSP(); 7135ffd83dbSDimitry Andric } 7145ffd83dbSDimitry Andric } 7155ffd83dbSDimitry Andric 7165ffd83dbSDimitry Andric // Get the whole contents of vector registers and let the logic here 7175ffd83dbSDimitry Andric // arrange the data properly. 7185ffd83dbSDimitry Andric 7195ffd83dbSDimitry Andric RegisterValue vr_val[MAX_VRS]; 7205ffd83dbSDimitry Andric Status error; 7215ffd83dbSDimitry Andric std::unique_ptr<DataBufferHeap> vr_data( 7225ffd83dbSDimitry Andric new DataBufferHeap(vrs * vr_size, 0)); 7235ffd83dbSDimitry Andric 7245ffd83dbSDimitry Andric for (uint32_t i = 0; i < vrs; i++) { 7255ffd83dbSDimitry Andric if (!m_reg_ctx->ReadRegister(vr[i], vr_val[i])) { 7265ffd83dbSDimitry Andric LLDB_LOG(m_log, LOG_PREFIX "Failed to read vector register contents"); 7275ffd83dbSDimitry Andric return ValueObjectSP(); 7285ffd83dbSDimitry Andric } 729bdd1243dSDimitry Andric if (!vr_val[i].GetAsMemoryData(*vr[i], vr_data->GetBytes() + i * vr_size, 7305ffd83dbSDimitry Andric vr_size, m_byte_order, error)) { 7315ffd83dbSDimitry Andric LLDB_LOG(m_log, LOG_PREFIX "Failed to extract vector register bytes"); 7325ffd83dbSDimitry Andric return ValueObjectSP(); 7335ffd83dbSDimitry Andric } 7345ffd83dbSDimitry Andric } 7355ffd83dbSDimitry Andric 7365ffd83dbSDimitry Andric // The compiler generated code seems to always put the vector elements at 7375ffd83dbSDimitry Andric // the end of the vector register, in case they don't occupy all of it. 7385ffd83dbSDimitry Andric // This offset variable handles this. 7395ffd83dbSDimitry Andric uint32_t offs = 0; 7405ffd83dbSDimitry Andric if (m_byte_size < vr_size) 7415ffd83dbSDimitry Andric offs = vr_size - m_byte_size; 7425ffd83dbSDimitry Andric 7435ffd83dbSDimitry Andric // copy extracted data to our buffer 7445ffd83dbSDimitry Andric memcpy(m_data_up->GetBytes(), vr_data->GetBytes() + offs, m_byte_size); 7455ffd83dbSDimitry Andric return BuildValueObject(); 7465ffd83dbSDimitry Andric } 7475ffd83dbSDimitry Andric 7485ffd83dbSDimitry Andric // get a struct return value 7495ffd83dbSDimitry Andric ValueObjectSP GetStructValueObject() { 7505ffd83dbSDimitry Andric // case 1: get from stack 7515ffd83dbSDimitry Andric if (m_byte_size > 2 * sizeof(uint64_t)) { 7525ffd83dbSDimitry Andric uint64_t addr; 7535ffd83dbSDimitry Andric auto reg = GetGPR(0); 7545ffd83dbSDimitry Andric if (!reg.GetRawData(addr)) 7555ffd83dbSDimitry Andric return {}; 7565ffd83dbSDimitry Andric 7575ffd83dbSDimitry Andric Status error; 7585ffd83dbSDimitry Andric size_t rc = m_process_sp->ReadMemory(addr, m_data_up->GetBytes(), 7595ffd83dbSDimitry Andric m_byte_size, error); 7605ffd83dbSDimitry Andric if (rc != m_byte_size) { 7615ffd83dbSDimitry Andric LLDB_LOG(m_log, LOG_PREFIX "Failed to read memory pointed by r3"); 7625ffd83dbSDimitry Andric return ValueObjectSP(); 7635ffd83dbSDimitry Andric } 7645ffd83dbSDimitry Andric return BuildValueObject(); 7655ffd83dbSDimitry Andric } 7665ffd83dbSDimitry Andric 7675ffd83dbSDimitry Andric // get number of children 7685ffd83dbSDimitry Andric const bool omit_empty_base_classes = true; 769*0fca6ea1SDimitry Andric auto n_or_err = m_type.GetNumChildren(omit_empty_base_classes, nullptr); 770*0fca6ea1SDimitry Andric if (!n_or_err) { 771*0fca6ea1SDimitry Andric LLDB_LOG_ERROR(m_log, n_or_err.takeError(), LOG_PREFIX "{0}"); 772*0fca6ea1SDimitry Andric return {}; 773*0fca6ea1SDimitry Andric } 774*0fca6ea1SDimitry Andric uint32_t n = *n_or_err; 7755ffd83dbSDimitry Andric if (!n) { 7765ffd83dbSDimitry Andric LLDB_LOG(m_log, LOG_PREFIX "No children found in struct"); 7775ffd83dbSDimitry Andric return {}; 7785ffd83dbSDimitry Andric } 7795ffd83dbSDimitry Andric 7805ffd83dbSDimitry Andric // case 2: homogeneous double or float aggregate 7815ffd83dbSDimitry Andric CompilerType elem_type; 7825ffd83dbSDimitry Andric if (m_type.IsHomogeneousAggregate(&elem_type)) { 7835ffd83dbSDimitry Andric uint32_t type_flags = elem_type.GetTypeInfo(); 784bdd1243dSDimitry Andric std::optional<uint64_t> elem_size = 785e8d8bef9SDimitry Andric elem_type.GetByteSize(m_process_sp.get()); 7865ffd83dbSDimitry Andric if (!elem_size) 7875ffd83dbSDimitry Andric return {}; 7885ffd83dbSDimitry Andric if (type_flags & eTypeIsComplex || !(type_flags & eTypeIsFloat)) { 7895ffd83dbSDimitry Andric LLDB_LOG(m_log, 7905ffd83dbSDimitry Andric LOG_PREFIX "Unexpected type found in homogeneous aggregate"); 7915ffd83dbSDimitry Andric return {}; 7925ffd83dbSDimitry Andric } 7935ffd83dbSDimitry Andric 7945ffd83dbSDimitry Andric for (uint32_t i = 0; i < n; i++) { 7955ffd83dbSDimitry Andric ValueSP val_sp = GetFloatValue(elem_type, i); 7965ffd83dbSDimitry Andric if (!val_sp) 7975ffd83dbSDimitry Andric return {}; 7985ffd83dbSDimitry Andric 7995ffd83dbSDimitry Andric // copy to buffer 8005ffd83dbSDimitry Andric Status error; 8015ffd83dbSDimitry Andric size_t rc = val_sp->GetScalar().GetAsMemoryData( 8025ffd83dbSDimitry Andric m_data_up->GetBytes() + m_dst_offs, *elem_size, m_byte_order, 8035ffd83dbSDimitry Andric error); 8045ffd83dbSDimitry Andric if (rc != *elem_size) { 8055ffd83dbSDimitry Andric LLDB_LOG(m_log, LOG_PREFIX "Failed to get float data"); 8065ffd83dbSDimitry Andric return {}; 8075ffd83dbSDimitry Andric } 8085ffd83dbSDimitry Andric m_dst_offs += *elem_size; 8095ffd83dbSDimitry Andric } 8105ffd83dbSDimitry Andric return BuildValueObject(); 8115ffd83dbSDimitry Andric } 8125ffd83dbSDimitry Andric 8135ffd83dbSDimitry Andric // case 3: get from GPRs 8145ffd83dbSDimitry Andric 8155ffd83dbSDimitry Andric // first, check if this is a packed struct or not 816bdd1243dSDimitry Andric auto ast = m_type.GetTypeSystem().dyn_cast_or_null<TypeSystemClang>(); 8175ffd83dbSDimitry Andric if (ast) { 8185ffd83dbSDimitry Andric clang::RecordDecl *record_decl = TypeSystemClang::GetAsRecordDecl(m_type); 8195ffd83dbSDimitry Andric 8205ffd83dbSDimitry Andric if (record_decl) { 8215ffd83dbSDimitry Andric auto attrs = record_decl->attrs(); 8225ffd83dbSDimitry Andric for (const auto &attr : attrs) { 8235ffd83dbSDimitry Andric if (attr->getKind() == clang::attr::Packed) { 8245ffd83dbSDimitry Andric m_packed = true; 8255ffd83dbSDimitry Andric break; 8265ffd83dbSDimitry Andric } 8275ffd83dbSDimitry Andric } 8285ffd83dbSDimitry Andric } 8295ffd83dbSDimitry Andric } 8305ffd83dbSDimitry Andric 8315ffd83dbSDimitry Andric LLDB_LOG(m_log, LOG_PREFIX "{0} struct", 8325ffd83dbSDimitry Andric m_packed ? "packed" : "not packed"); 8335ffd83dbSDimitry Andric 8345ffd83dbSDimitry Andric for (uint32_t i = 0; i < n; i++) { 8355ffd83dbSDimitry Andric std::string name; 8365ffd83dbSDimitry Andric uint32_t size; 837*0fca6ea1SDimitry Andric (void)GetChildType(i, name, size); 8385ffd83dbSDimitry Andric // NOTE: the offset returned by GetChildCompilerTypeAtIndex() 8395ffd83dbSDimitry Andric // can't be used because it never considers alignment bytes 8405ffd83dbSDimitry Andric // between struct fields. 8415ffd83dbSDimitry Andric LLDB_LOG(m_log, LOG_PREFIX "field={0}, size={1}", name, size); 8425ffd83dbSDimitry Andric if (!ExtractField(size)) 8435ffd83dbSDimitry Andric return ValueObjectSP(); 8445ffd83dbSDimitry Andric } 8455ffd83dbSDimitry Andric 8465ffd83dbSDimitry Andric return BuildValueObject(); 8475ffd83dbSDimitry Andric } 8485ffd83dbSDimitry Andric 8495ffd83dbSDimitry Andric // extract 'size' bytes at 'offs' from GPRs 8505ffd83dbSDimitry Andric bool ExtractFromRegs(int32_t offs, uint32_t size, void *buf) { 8515ffd83dbSDimitry Andric while (size) { 8525ffd83dbSDimitry Andric auto reg = GetGPRByOffs(offs); 8535ffd83dbSDimitry Andric if (!reg.IsValid()) 8545ffd83dbSDimitry Andric return false; 8555ffd83dbSDimitry Andric 8565ffd83dbSDimitry Andric uint32_t n = std::min(reg.Avail(), size); 8575ffd83dbSDimitry Andric uint64_t raw_data; 8585ffd83dbSDimitry Andric 8595ffd83dbSDimitry Andric if (!reg.GetRawData(raw_data)) 8605ffd83dbSDimitry Andric return false; 8615ffd83dbSDimitry Andric 8625ffd83dbSDimitry Andric memcpy(buf, (char *)&raw_data + reg.Offs(), n); 8635ffd83dbSDimitry Andric offs += n; 8645ffd83dbSDimitry Andric size -= n; 8655ffd83dbSDimitry Andric buf = (char *)buf + n; 8665ffd83dbSDimitry Andric } 8675ffd83dbSDimitry Andric return true; 8685ffd83dbSDimitry Andric } 8695ffd83dbSDimitry Andric 8705ffd83dbSDimitry Andric // extract one field from GPRs and put it in our buffer 8715ffd83dbSDimitry Andric bool ExtractField(uint32_t size) { 8725ffd83dbSDimitry Andric auto reg = GetGPRByOffs(m_src_offs); 8735ffd83dbSDimitry Andric if (!reg.IsValid()) 8745ffd83dbSDimitry Andric return false; 8755ffd83dbSDimitry Andric 8765ffd83dbSDimitry Andric // handle padding 8775ffd83dbSDimitry Andric if (!m_packed) { 8785ffd83dbSDimitry Andric uint32_t n = m_src_offs % size; 8795ffd83dbSDimitry Andric 8805ffd83dbSDimitry Andric // not 'size' bytes aligned 8815ffd83dbSDimitry Andric if (n) { 8825ffd83dbSDimitry Andric LLDB_LOG(m_log, 8835ffd83dbSDimitry Andric LOG_PREFIX "Extracting {0} alignment bytes at offset {1}", n, 8845ffd83dbSDimitry Andric m_src_offs); 8855ffd83dbSDimitry Andric // get alignment bytes 8865ffd83dbSDimitry Andric if (!ExtractFromRegs(m_src_offs, n, m_data_up->GetBytes() + m_dst_offs)) 8875ffd83dbSDimitry Andric return false; 8885ffd83dbSDimitry Andric m_src_offs += n; 8895ffd83dbSDimitry Andric m_dst_offs += n; 8905ffd83dbSDimitry Andric } 8915ffd83dbSDimitry Andric } 8925ffd83dbSDimitry Andric 8935ffd83dbSDimitry Andric // get field 8945ffd83dbSDimitry Andric LLDB_LOG(m_log, LOG_PREFIX "Extracting {0} field bytes at offset {1}", size, 8955ffd83dbSDimitry Andric m_src_offs); 8965ffd83dbSDimitry Andric if (!ExtractFromRegs(m_src_offs, size, m_data_up->GetBytes() + m_dst_offs)) 8975ffd83dbSDimitry Andric return false; 8985ffd83dbSDimitry Andric m_src_offs += size; 8995ffd83dbSDimitry Andric m_dst_offs += size; 9005ffd83dbSDimitry Andric return true; 9015ffd83dbSDimitry Andric } 9025ffd83dbSDimitry Andric 9035ffd83dbSDimitry Andric // get child 904*0fca6ea1SDimitry Andric llvm::Expected<CompilerType> GetChildType(uint32_t i, std::string &name, 905*0fca6ea1SDimitry Andric uint32_t &size) { 9065ffd83dbSDimitry Andric // GetChild constant inputs 9075ffd83dbSDimitry Andric const bool transparent_pointers = false; 9085ffd83dbSDimitry Andric const bool omit_empty_base_classes = true; 9095ffd83dbSDimitry Andric const bool ignore_array_bounds = false; 9105ffd83dbSDimitry Andric // GetChild output params 9115ffd83dbSDimitry Andric int32_t child_offs; 9125ffd83dbSDimitry Andric uint32_t child_bitfield_bit_size; 9135ffd83dbSDimitry Andric uint32_t child_bitfield_bit_offset; 9145ffd83dbSDimitry Andric bool child_is_base_class; 9155ffd83dbSDimitry Andric bool child_is_deref_of_parent; 9165ffd83dbSDimitry Andric ValueObject *valobj = nullptr; 9175ffd83dbSDimitry Andric uint64_t language_flags; 9185ffd83dbSDimitry Andric ExecutionContext exe_ctx; 9195ffd83dbSDimitry Andric m_thread.CalculateExecutionContext(exe_ctx); 9205ffd83dbSDimitry Andric 9215ffd83dbSDimitry Andric return m_type.GetChildCompilerTypeAtIndex( 9225ffd83dbSDimitry Andric &exe_ctx, i, transparent_pointers, omit_empty_base_classes, 9235ffd83dbSDimitry Andric ignore_array_bounds, name, size, child_offs, child_bitfield_bit_size, 9245ffd83dbSDimitry Andric child_bitfield_bit_offset, child_is_base_class, 9255ffd83dbSDimitry Andric child_is_deref_of_parent, valobj, language_flags); 9265ffd83dbSDimitry Andric } 9275ffd83dbSDimitry Andric }; 9285ffd83dbSDimitry Andric 9295ffd83dbSDimitry Andric #undef LOG_PREFIX 9305ffd83dbSDimitry Andric 9315ffd83dbSDimitry Andric } // anonymous namespace 9325ffd83dbSDimitry Andric 9335ffd83dbSDimitry Andric ValueObjectSP 9345ffd83dbSDimitry Andric ABISysV_ppc64::GetReturnValueObjectSimple(Thread &thread, 9355ffd83dbSDimitry Andric CompilerType &type) const { 9365ffd83dbSDimitry Andric if (!type) 9375ffd83dbSDimitry Andric return ValueObjectSP(); 9385ffd83dbSDimitry Andric 9395ffd83dbSDimitry Andric auto exp_extractor = ReturnValueExtractor::Create(thread, type); 9405ffd83dbSDimitry Andric if (!exp_extractor) { 94181ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Expressions); 9425ffd83dbSDimitry Andric LLDB_LOG_ERROR(log, exp_extractor.takeError(), 9435ffd83dbSDimitry Andric "Extracting return value failed: {0}"); 9445ffd83dbSDimitry Andric return ValueObjectSP(); 9455ffd83dbSDimitry Andric } 9465ffd83dbSDimitry Andric 9475ffd83dbSDimitry Andric return exp_extractor.get().GetValue(); 9485ffd83dbSDimitry Andric } 9495ffd83dbSDimitry Andric 9505ffd83dbSDimitry Andric ValueObjectSP ABISysV_ppc64::GetReturnValueObjectImpl( 9515ffd83dbSDimitry Andric Thread &thread, CompilerType &return_compiler_type) const { 9525ffd83dbSDimitry Andric return GetReturnValueObjectSimple(thread, return_compiler_type); 9535ffd83dbSDimitry Andric } 9545ffd83dbSDimitry Andric 9555ffd83dbSDimitry Andric bool ABISysV_ppc64::CreateFunctionEntryUnwindPlan(UnwindPlan &unwind_plan) { 9565ffd83dbSDimitry Andric unwind_plan.Clear(); 9575ffd83dbSDimitry Andric unwind_plan.SetRegisterKind(eRegisterKindDWARF); 9585ffd83dbSDimitry Andric 9595ffd83dbSDimitry Andric uint32_t lr_reg_num; 9605ffd83dbSDimitry Andric uint32_t sp_reg_num; 9615ffd83dbSDimitry Andric uint32_t pc_reg_num; 9625ffd83dbSDimitry Andric 9635ffd83dbSDimitry Andric if (GetByteOrder() == lldb::eByteOrderLittle) { 9645ffd83dbSDimitry Andric lr_reg_num = ppc64le_dwarf::dwarf_lr_ppc64le; 9655ffd83dbSDimitry Andric sp_reg_num = ppc64le_dwarf::dwarf_r1_ppc64le; 9665ffd83dbSDimitry Andric pc_reg_num = ppc64le_dwarf::dwarf_pc_ppc64le; 9675ffd83dbSDimitry Andric } else { 9685ffd83dbSDimitry Andric lr_reg_num = ppc64_dwarf::dwarf_lr_ppc64; 9695ffd83dbSDimitry Andric sp_reg_num = ppc64_dwarf::dwarf_r1_ppc64; 9705ffd83dbSDimitry Andric pc_reg_num = ppc64_dwarf::dwarf_pc_ppc64; 9715ffd83dbSDimitry Andric } 9725ffd83dbSDimitry Andric 9735ffd83dbSDimitry Andric UnwindPlan::RowSP row(new UnwindPlan::Row); 9745ffd83dbSDimitry Andric 9755ffd83dbSDimitry Andric // Our Call Frame Address is the stack pointer value 9765ffd83dbSDimitry Andric row->GetCFAValue().SetIsRegisterPlusOffset(sp_reg_num, 0); 9775ffd83dbSDimitry Andric 9785ffd83dbSDimitry Andric // The previous PC is in the LR 9795ffd83dbSDimitry Andric row->SetRegisterLocationToRegister(pc_reg_num, lr_reg_num, true); 9805ffd83dbSDimitry Andric unwind_plan.AppendRow(row); 9815ffd83dbSDimitry Andric 9825ffd83dbSDimitry Andric // All other registers are the same. 9835ffd83dbSDimitry Andric 9845ffd83dbSDimitry Andric unwind_plan.SetSourceName("ppc64 at-func-entry default"); 9855ffd83dbSDimitry Andric unwind_plan.SetSourcedFromCompiler(eLazyBoolNo); 9865ffd83dbSDimitry Andric 9875ffd83dbSDimitry Andric return true; 9885ffd83dbSDimitry Andric } 9895ffd83dbSDimitry Andric 9905ffd83dbSDimitry Andric bool ABISysV_ppc64::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) { 9915ffd83dbSDimitry Andric unwind_plan.Clear(); 9925ffd83dbSDimitry Andric unwind_plan.SetRegisterKind(eRegisterKindDWARF); 9935ffd83dbSDimitry Andric 9945ffd83dbSDimitry Andric uint32_t sp_reg_num; 9955ffd83dbSDimitry Andric uint32_t pc_reg_num; 9965ffd83dbSDimitry Andric uint32_t cr_reg_num; 9975ffd83dbSDimitry Andric 9985ffd83dbSDimitry Andric if (GetByteOrder() == lldb::eByteOrderLittle) { 9995ffd83dbSDimitry Andric sp_reg_num = ppc64le_dwarf::dwarf_r1_ppc64le; 10005ffd83dbSDimitry Andric pc_reg_num = ppc64le_dwarf::dwarf_lr_ppc64le; 10015ffd83dbSDimitry Andric cr_reg_num = ppc64le_dwarf::dwarf_cr_ppc64le; 10025ffd83dbSDimitry Andric } else { 10035ffd83dbSDimitry Andric sp_reg_num = ppc64_dwarf::dwarf_r1_ppc64; 10045ffd83dbSDimitry Andric pc_reg_num = ppc64_dwarf::dwarf_lr_ppc64; 10055ffd83dbSDimitry Andric cr_reg_num = ppc64_dwarf::dwarf_cr_ppc64; 10065ffd83dbSDimitry Andric } 10075ffd83dbSDimitry Andric 10085ffd83dbSDimitry Andric UnwindPlan::RowSP row(new UnwindPlan::Row); 10095ffd83dbSDimitry Andric const int32_t ptr_size = 8; 1010fe6060f1SDimitry Andric row->SetUnspecifiedRegistersAreUndefined(true); 10115ffd83dbSDimitry Andric row->GetCFAValue().SetIsRegisterDereferenced(sp_reg_num); 10125ffd83dbSDimitry Andric 10135ffd83dbSDimitry Andric row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * 2, true); 10145ffd83dbSDimitry Andric row->SetRegisterLocationToIsCFAPlusOffset(sp_reg_num, 0, true); 10155ffd83dbSDimitry Andric row->SetRegisterLocationToAtCFAPlusOffset(cr_reg_num, ptr_size, true); 10165ffd83dbSDimitry Andric 10175ffd83dbSDimitry Andric unwind_plan.AppendRow(row); 10185ffd83dbSDimitry Andric unwind_plan.SetSourceName("ppc64 default unwind plan"); 10195ffd83dbSDimitry Andric unwind_plan.SetSourcedFromCompiler(eLazyBoolNo); 10205ffd83dbSDimitry Andric unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo); 10215ffd83dbSDimitry Andric unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo); 10225ffd83dbSDimitry Andric unwind_plan.SetReturnAddressRegister(pc_reg_num); 10235ffd83dbSDimitry Andric return true; 10245ffd83dbSDimitry Andric } 10255ffd83dbSDimitry Andric 10265ffd83dbSDimitry Andric bool ABISysV_ppc64::RegisterIsVolatile(const RegisterInfo *reg_info) { 10275ffd83dbSDimitry Andric return !RegisterIsCalleeSaved(reg_info); 10285ffd83dbSDimitry Andric } 10295ffd83dbSDimitry Andric 10305ffd83dbSDimitry Andric // See "Register Usage" in the 10315ffd83dbSDimitry Andric // "System V Application Binary Interface" 10325ffd83dbSDimitry Andric // "64-bit PowerPC ELF Application Binary Interface Supplement" current version 10335ffd83dbSDimitry Andric // is 2 released 2015 at 10345ffd83dbSDimitry Andric // https://members.openpowerfoundation.org/document/dl/576 10355ffd83dbSDimitry Andric bool ABISysV_ppc64::RegisterIsCalleeSaved(const RegisterInfo *reg_info) { 10365ffd83dbSDimitry Andric if (reg_info) { 10375ffd83dbSDimitry Andric // Preserved registers are : 10385ffd83dbSDimitry Andric // r1,r2,r13-r31 10395ffd83dbSDimitry Andric // cr2-cr4 (partially preserved) 10405ffd83dbSDimitry Andric // f14-f31 (not yet) 10415ffd83dbSDimitry Andric // v20-v31 (not yet) 10425ffd83dbSDimitry Andric // vrsave (not yet) 10435ffd83dbSDimitry Andric 10445ffd83dbSDimitry Andric const char *name = reg_info->name; 10455ffd83dbSDimitry Andric if (name[0] == 'r') { 10465ffd83dbSDimitry Andric if ((name[1] == '1' || name[1] == '2') && name[2] == '\0') 10475ffd83dbSDimitry Andric return true; 10485ffd83dbSDimitry Andric if (name[1] == '1' && name[2] > '2') 10495ffd83dbSDimitry Andric return true; 10505ffd83dbSDimitry Andric if ((name[1] == '2' || name[1] == '3') && name[2] != '\0') 10515ffd83dbSDimitry Andric return true; 10525ffd83dbSDimitry Andric } 10535ffd83dbSDimitry Andric 10545ffd83dbSDimitry Andric if (name[0] == 'f' && name[1] >= '0' && name[2] <= '9') { 10555ffd83dbSDimitry Andric if (name[2] == '\0') 10565ffd83dbSDimitry Andric return false; 10575ffd83dbSDimitry Andric if (name[1] == '1' && name[2] >= '4') 10585ffd83dbSDimitry Andric return true; 10595ffd83dbSDimitry Andric if ((name[1] == '2' || name[1] == '3') && name[2] != '\0') 10605ffd83dbSDimitry Andric return true; 10615ffd83dbSDimitry Andric } 10625ffd83dbSDimitry Andric 10635ffd83dbSDimitry Andric if (name[0] == 's' && name[1] == 'p' && name[2] == '\0') // sp 10645ffd83dbSDimitry Andric return true; 10655ffd83dbSDimitry Andric if (name[0] == 'f' && name[1] == 'p' && name[2] == '\0') // fp 10665ffd83dbSDimitry Andric return false; 10675ffd83dbSDimitry Andric if (name[0] == 'p' && name[1] == 'c' && name[2] == '\0') // pc 10685ffd83dbSDimitry Andric return true; 10695ffd83dbSDimitry Andric } 10705ffd83dbSDimitry Andric return false; 10715ffd83dbSDimitry Andric } 10725ffd83dbSDimitry Andric 10735ffd83dbSDimitry Andric void ABISysV_ppc64::Initialize() { 10745ffd83dbSDimitry Andric PluginManager::RegisterPlugin( 10755ffd83dbSDimitry Andric GetPluginNameStatic(), "System V ABI for ppc64 targets", CreateInstance); 10765ffd83dbSDimitry Andric } 10775ffd83dbSDimitry Andric 10785ffd83dbSDimitry Andric void ABISysV_ppc64::Terminate() { 10795ffd83dbSDimitry Andric PluginManager::UnregisterPlugin(CreateInstance); 10805ffd83dbSDimitry Andric } 1081