From nobody Mon Sep 17 00:00:00 2001 From: Alexander Astapchuk Date: Thu, 7 Dec 2006 16:36:13 +0600 Subject: [PATCH] [drlvm][fastcc]preliminary: jitrino part --- .../codegenerator/ia32/Ia32CallingConvention.cpp | 377 ++++++++++++++--------- .../src/codegenerator/ia32/Ia32CallingConvention.h | 116 ++++--- .../src/codegenerator/ia32/Ia32IRManager.cpp | 50 ++- vm/jitrino/src/codegenerator/ia32/Ia32IRManager.h | 21 + vm/jitrino/src/codegenerator/ia32/Ia32Inst.h | 2 vm/jitrino/src/vm/VMInterface.h | 5 vm/jitrino/src/vm/drl/DrlVMInterface.cpp | 20 + vm/jitrino/src/vm/drl/DrlVMInterface.h | 21 - 8 files changed, 382 insertions(+), 230 deletions(-) f1dabe46f9c38bd2218249d8913c90788385fda4 diff --git a/vm/jitrino/src/codegenerator/ia32/Ia32CallingConvention.cpp b/vm/jitrino/src/codegenerator/ia32/Ia32CallingConvention.cpp index 77a926e..d8ca612 100644 --- a/vm/jitrino/src/codegenerator/ia32/Ia32CallingConvention.cpp +++ b/vm/jitrino/src/codegenerator/ia32/Ia32CallingConvention.cpp @@ -21,207 +21,290 @@ #include "Ia32CallingConvention.h" #include "Ia32IRManager.h" +#include "callconv.h" + +namespace Jitrino { +namespace Ia32 { + +STDCALLCallingConvention CallingConvention_STDCALL; +DRLCallingConvention CallingConvention_DRL; +CDECLCallingConvention CallingConvention_CDECL; +FastCallCallingConvention CallingConvention_Fastcall; +DRLFastCallCallingConvention CallingConvention_DRLFast; + +static bool isFloatPointType(Type::Tag typeTag) +{ + assert(typeTag != Type::Float); + return (typeTag == Type::Double) || (typeTag == Type::Single); +} -namespace Jitrino{ -namespace Ia32{ const CallingConvention * CallingConvention::str2cc(const char * cc_name) { - if( NULL == cc_name ) { // default + if (NULL == cc_name) { // default return &CallingConvention_STDCALL; } - if( !strcmpi(cc_name, "stdcall") ) { + if (!strcmpi(cc_name, "stdcall")) { return &CallingConvention_STDCALL; } - if( !strcmpi(cc_name, "drl") ) { + if (!strcmpi(cc_name, "drl")) { return &CallingConvention_DRL; } - if( !strcmpi(cc_name, "cdecl") ) { + if (!strcmpi(cc_name, "cdecl")) { + return &CallingConvention_CDECL; + } + + if (!strcmpi(cc_name, "cdecl")) { return &CallingConvention_CDECL; } - assert( false ); - return NULL; -} - - -//======================================================================================== -STDCALLCallingConvention CallingConvention_STDCALL; -DRLCallingConvention CallingConvention_DRL; -CDECLCallingConvention CallingConvention_CDECL; + if (!strcmpi(cc_name, "fastcall")) { + return &CallingConvention_Fastcall; + } -//======================================================================================== -// class STDCALLCallingConvention -//======================================================================================== + if (!strcmpi(cc_name, "drlfast")) { + return &CallingConvention_DRLFast; + } + assert(false); + return NULL; +} #ifdef _EM64T_ const RegName fastCallGPRegs[6] = {RegName_RDI, RegName_RSI, RegName_RDX, RegName_RCX, RegName_R8, RegName_R9} ; const RegName fastCallFPRegs[8] = {RegName_XMM0,RegName_XMM1,RegName_XMM2,RegName_XMM3,RegName_XMM4,RegName_XMM5,RegName_XMM6,RegName_XMM7}; #endif -//______________________________________________________________________________________ -void STDCALLCallingConvention::getOpndInfo(ArgKind kind, uint32 count, OpndInfo * infos)const +void CallingConventionBase::getOpndInfo(ArgKind kind, uint32 count, OpndInfo * infos) const { if (kind==ArgKind_InArg){ #ifdef _EM64T_ - uint32 gpreg = 0; - uint32 fpreg = 0; -#endif - for (uint32 i=0; iType::Float ||typeTag=Type::Single) && fpreg < lengthof(fastCallFPRegs))) { - infos[i].slotCount=1; - infos[i].slots[0]=fastCallFPRegs[fpreg]; - infos[i].isReg=true; + } + else if(isFloatPointType(typeTag) && fpreg < lengthof(fastCallFPRegs)) { + info.isReg = true; + info.slots[0] = fastCallFPRegs[fpreg]; fpreg++; - } else { - infos[i].slotCount=1; - infos[i].slots[0]=RegName_Null; - infos[i].isReg=false; } - - + else { + info.isReg = false; + info.slots[0] = RegName_Null; + } + } #else - OpndSize size=IRManager::getTypeSize(typeTag); - assert(size!=OpndSize_Null && size<=OpndSize_64); - - infos[i].slotCount=1; - infos[i].slots[0]=RegName_Null; - infos[i].isReg=false; - - if (size==OpndSize_64){ - infos[i].slotCount=2; - infos[i].slots[1]=RegName_Null; + // Presume everything is passed on stack. + // Derivatives will fix when needed. + for (uint32 i=0; i= OpndSize_64) { + infos[i].slotCount = 2; + infos[i].slots[0] = RegName_Null; + infos[i].isReg = false; } + } #endif + return; + } - } - }else{ - for (uint32 i=0; i0){ - infos[i].slotCount=0; - }else{ - switch(typeTag){ - case Type::Void: - infos[i].slotCount=0; - break; - case Type::Float: - case Type::Double: - case Type::Single: + assert(kind == ArgKind_RetArg); + // The return value's expected to be singular or none + if (count == 0) { + return; + } + assert(count == 1); + + Type::Tag typeTag = infos[0].typeTag; + + if (typeTag == Type::Void) { + infos[0].slotCount = 0; + } + else if (isFloatPointType(typeTag)) { + infos[0].slotCount = 1; #ifdef _EM64T_ - infos[i].slotCount=1; - infos[i].slots[0]=RegName_XMM0; + infos[0].slots[0] = RegName_XMM0; #else - infos[i].slotCount=1; - infos[i].slots[0]=RegName_FP0; + infos[0].slots[0] = RegName_FP0; #endif - break; - default: - { - OpndSize size=IRManager::getTypeSize(typeTag); + } + else { + // 128 bits are not expected in Java world + assert(IRManager::getTypeSize(typeTag) != OpndSize_128); + infos[0].slotCount = 1; #ifdef _EM64T_ - infos[i].slotCount=1; - infos[i].slots[0]=RegName_RAX; - - if (size==OpndSize_128){ - infos[i].slotCount=2; - infos[i].slots[1]=RegName_RDX; - } + infos[0].slots[0] = RegName_RAX; #else - assert(size!=OpndSize_Null && size<=OpndSize_64); - - infos[i].slotCount=1; - infos[i].slots[0]=RegName_EAX; - - if (size==OpndSize_64){ - infos[i].slotCount=2; - infos[i].slots[1]=RegName_EDX; - } -#endif - } - } - } + infos[0].slots[0] = RegName_EAX; + OpndSize size = IRManager::getTypeSize(typeTag); + if (size == OpndSize_64) { + infos[0].slotCount = 2; + infos[0].slots[1] = RegName_EDX; } +#endif } } -//______________________________________________________________________________________ -Constraint STDCALLCallingConvention::getCalleeSavedRegs(OpndKind regKind)const +Constraint CallingConventionBase::getCalleeSavedRegs(OpndKind regKind) const { - switch (regKind){ - case OpndKind_GPReg: + Constraint calleeSave; + if (regKind == OpndKind_GPReg) { + #ifdef _EM64T_ - return (Constraint(RegName_RBX)|RegName_RBP|RegName_R12|RegName_R13|RegName_R14|RegName_R15); + calleeSave = (Constraint(RegName_RBX)|RegName_RBP| + RegName_R12|RegName_R13|RegName_R14|RegName_R15); #else - return (Constraint(RegName_EBX)|RegName_EBP|RegName_ESI|RegName_EDI); + calleeSave = (Constraint(RegName_EBX)|RegName_EBP|RegName_ESI|RegName_EDI); #endif - default: - return Constraint(); } + return calleeSave; } + + #ifdef _EM64T_ -//______________________________________________________________________________________ -void CDECLCallingConvention::getOpndInfo(ArgKind kind, uint32 count, OpndInfo * infos)const + +void CDECLCallingConvention::getOpndInfo(ArgKind kind, uint32 count, OpndInfo * infos)const { - if (kind==ArgKind_InArg){ - for (uint32 i=0; i0){ - infos[i].isReg=false; - infos[i].slotCount=0; - }else{ - switch(typeTag){ - case Type::Void: - infos[i].isReg=false; - infos[i].slotCount=0; - break; - case Type::Float: - case Type::Double: - case Type::Single: - infos[i].isReg=true; - infos[i].slotCount=1; - infos[i].slots[0]=RegName_XMM0; - break; - default: - { - OpndSize size=IRManager::getTypeSize(typeTag); - infos[i].slotCount=1; - infos[i].slots[0]=RegName_RAX; - infos[i].isReg=true; - - if (size==OpndSize_128){ - infos[i].slotCount=2; - infos[i].slots[1]=RegName_RDX; - } - } - } - } + if (kind == ArgKind_InArg) { + for(uint32 i=0; i CallingConventionVector; - -//======================================================================================== -// class STDCALLCallingConvention -//======================================================================================== -/** Implementation of CallingConvention for the STDCALL calling convention -*/ - -class STDCALLCallingConvention: public CallingConvention -{ -public: - - virtual ~STDCALLCallingConvention() {} - virtual void getOpndInfo(ArgKind kind, uint32 argCount, OpndInfo * infos)const; - virtual Constraint getCalleeSavedRegs(OpndKind regKind)const; +/** + * Provides common, platform-wide characteristics of calling conventions. + */ +class CallingConventionBase : public CallingConvention +{ +protected: + virtual Constraint getCalleeSavedRegs(OpndKind regKind) const; + virtual void getOpndInfo(ArgKind kind, uint32 argCount, OpndInfo * infos) const; #ifdef _EM64T_ - virtual bool calleeRestoresStack()const{ return false; } + virtual bool calleeRestoresStack(void) const { return false; } #else - virtual bool calleeRestoresStack()const{ return true; } + virtual bool calleeRestoresStack(void) const { return true; } #endif - virtual bool pushLastToFirst()const{ return true; } - + virtual bool pushLastToFirst(void) const { return true; } }; -//======================================================================================== -// class DRLCallingConvention -//======================================================================================== -/** Implementation of CallingConvention for the DRL IA32 calling convention -*/ -class DRLCallingConvention: public STDCALLCallingConvention + +/** STDCALL implementation.*/ +class STDCALLCallingConvention: public CallingConventionBase { public: - virtual ~DRLCallingConvention() {} - virtual bool pushLastToFirst()const{ return false; } - + virtual ~STDCALLCallingConvention() {} }; -//======================================================================================== -// class CDECLCallingConvention -//======================================================================================== -/** Implementation of CallingConvention for the CDECL calling convention -*/ -class CDECLCallingConvention: public STDCALLCallingConvention +/** Implementation of CallingConvention for the CDECL calling convention */ +class CDECLCallingConvention: public CallingConventionBase { public: virtual ~CDECLCallingConvention() {} @@ -149,9 +135,49 @@ #ifdef _EM64T_ #endif }; +/** Implementation of default convention for managed code on IA32.*/ +class DRLCallingConvention: public CallingConventionBase +{ +public: + virtual ~DRLCallingConvention() {} + virtual bool pushLastToFirst(void) const { return false; } + +}; + +#ifdef _EM64T_ + +class FastCallCallingConvention : public CallingConventionBase {}; +class DRLFastCallCallingConvention : public CallingConventionBase {}; + +#else // _EM64T_ +class FastCallCallingConvention : public CallingConventionBase +{ + virtual void getOpndInfo(ArgKind kind, uint32 argCount, OpndInfo * infos) const; + + virtual bool pushLastToFirst(void) const + { + return false; + } +}; + +class DRLFastCallCallingConvention : public CallingConventionBase +{ + virtual void getOpndInfo(ArgKind kind, uint32 argCount, OpndInfo * infos) const; + virtual Constraint getCalleeSavedRegs(OpndKind regKind) const; + + virtual bool pushLastToFirst(void) const + { + return false; + } +}; + +#endif // ~ifdef _EM64T_ + extern STDCALLCallingConvention CallingConvention_STDCALL; extern DRLCallingConvention CallingConvention_DRL; extern CDECLCallingConvention CallingConvention_CDECL; +extern FastCallCallingConvention CallingConvention_Fastcall; +extern DRLFastCallCallingConvention CallingConvention_DRLFast; }; // namespace Ia32 } diff --git a/vm/jitrino/src/codegenerator/ia32/Ia32IRManager.cpp b/vm/jitrino/src/codegenerator/ia32/Ia32IRManager.cpp index 4df1c7b..fbd611e 100644 --- a/vm/jitrino/src/codegenerator/ia32/Ia32IRManager.cpp +++ b/vm/jitrino/src/codegenerator/ia32/Ia32IRManager.cpp @@ -1218,30 +1218,42 @@ #endif return instList; } -//_________________________________________________________________________________________________ -const CallingConvention * IRManager::getCallingConvention(CompilationInterface::RuntimeHelperId helperId)const -{ - CompilationInterface::VmCallingConvention callConv=compilationInterface.getRuntimeHelperCallingConvention(helperId); - switch (callConv){ - case CompilationInterface::CallingConvention_Drl: - return &CallingConvention_DRL; - case CompilationInterface::CallingConvention_Stdcall: - return &CallingConvention_STDCALL; - case CompilationInterface::CallingConvention_Cdecl: - return &CallingConvention_CDECL; - default: - assert(0); - return NULL; - } +const CallingConvention* IRManager::getCallingConvention(MethodDesc * methodDesc) const +{ + return getDefaultManagedCallingConvention(); } -//_________________________________________________________________________________________________ -const CallingConvention * IRManager::getCallingConvention(MethodDesc * methodDesc)const +const CallingConvention* IRManager::getDefaultManagedCallingConvention(void) const { - return &CallingConvention_DRL; + return getCallingConvention(compilationInterface.getManagedCallingConvention()); } -//_________________________________________________________________________________________________ +const CallingConvention* IRManager::getCallingConvention( + CompilationInterface::RuntimeHelperId helperId) const +{ + return getCallingConvention(compilationInterface.getRuntimeHelperCallingConvention(helperId)); +} + +const CallingConvention* IRManager::getCallingConvention( + CompilationInterface::VmCallingConvention vmCC) +{ + switch(vmCC) { + case CompilationInterface::CallingConvention_Drl: + return &CallingConvention_DRL; + case CompilationInterface::CallingConvention_DRLFast: + return &CallingConvention_DRLFast; + case CompilationInterface::CallingConvention_Stdcall: + return &CallingConvention_STDCALL; + case CompilationInterface::CallingConvention_Cdecl: + return &CallingConvention_CDECL; + case CompilationInterface::CallingConvention_Fastcall: + return &CallingConvention_Fastcall; + default: + assert(0); + } + return NULL; +} + Opnd * IRManager::defArg(Type * type, uint32 position) { assert(NULL != entryPointInst); diff --git a/vm/jitrino/src/codegenerator/ia32/Ia32IRManager.h b/vm/jitrino/src/codegenerator/ia32/Ia32IRManager.h index ab0621a..38acaa9 100644 --- a/vm/jitrino/src/codegenerator/ia32/Ia32IRManager.h +++ b/vm/jitrino/src/codegenerator/ia32/Ia32IRManager.h @@ -255,11 +255,22 @@ public: void setHasNonExceptionCalls(){ hasNonExceptionCalls=true; } bool getHasNonExceptionCalls()const{ return hasNonExceptionCalls; } //----------------------------------------------------------------------------------------------- - const CallingConvention * getCallingConvention(CompilationInterface::RuntimeHelperId helperId)const; - - const CallingConvention * getCallingConvention(MethodDesc * methodDesc)const; - - const CallingConvention * getDefaultManagedCallingConvention() const { return &CallingConvention_DRL; } + /** + * Returns calling convention for the given runtime helper. + */ + const CallingConvention * getCallingConvention(CompilationInterface::RuntimeHelperId helperId) const; + /** + * Returns calling convention for the given method. + */ + const CallingConvention * getCallingConvention(MethodDesc * methodDesc) const; + /** + * Returns default calling convention for managed code. + */ + const CallingConvention * getDefaultManagedCallingConvention(void) const; + /** + * Returns CallingConvention object for the given VmCallingConvention id. + */ + static const CallingConvention * getCallingConvention(CompilationInterface::VmCallingConvention vmCC); EntryPointPseudoInst * getEntryPointInst()const { return entryPointInst; } diff --git a/vm/jitrino/src/codegenerator/ia32/Ia32Inst.h b/vm/jitrino/src/codegenerator/ia32/Ia32Inst.h index ebfe705..7726689 100644 --- a/vm/jitrino/src/codegenerator/ia32/Ia32Inst.h +++ b/vm/jitrino/src/codegenerator/ia32/Ia32Inst.h @@ -1165,7 +1165,7 @@ public: void pushInfo(Inst::OpndRole role, Type::Tag typeTag) { CallingConvention::OpndInfo info; - info.typeTag=(uint32)typeTag; info.slotCount=0; + info.typeTag=typeTag; info.slotCount=0; StlVector & infos = getInfos(role); infos.push_back(info); } diff --git a/vm/jitrino/src/vm/VMInterface.h b/vm/jitrino/src/vm/VMInterface.h index 4cc4305..fc0bbf6 100644 --- a/vm/jitrino/src/vm/VMInterface.h +++ b/vm/jitrino/src/vm/VMInterface.h @@ -531,9 +531,12 @@ public: virtual bool mayInlineObjectSynchronization(ObjectSynchronizationInfo & syncInfo) = 0; enum VmCallingConvention { - CallingConvention_Drl = 0, + CallingConvention_Unknown, + CallingConvention_Drl, + CallingConvention_DRLFast, CallingConvention_Stdcall, CallingConvention_Cdecl, + CallingConvention_Fastcall, Num_CallingConvention }; diff --git a/vm/jitrino/src/vm/drl/DrlVMInterface.cpp b/vm/jitrino/src/vm/drl/DrlVMInterface.cpp index 97e8968..899c124 100644 --- a/vm/jitrino/src/vm/drl/DrlVMInterface.cpp +++ b/vm/jitrino/src/vm/drl/DrlVMInterface.cpp @@ -655,6 +655,26 @@ DrlVMCompilationInterface::setMethodHasS } CompilationInterface::VmCallingConvention +DrlVMCompilationInterface::toVmCC(CallingConvention cc) +{ + switch(cc) { + case CC_Vm: return CallingConvention_Drl; + case CC_Stdcall: return CallingConvention_Stdcall; + case CC_Cdecl: return CallingConvention_Cdecl; + case CC_Fastcall: return CallingConvention_Fastcall; + case CC_DRLFast: return CallingConvention_DRLFast; + default: assert(false); + } + return CallingConvention_Unknown; +} + +CompilationInterface::VmCallingConvention +DrlVMCompilationInterface::getManagedCallingConvention(void) +{ + return toVmCC(vm_managed_calling_convention()); +} + +CompilationInterface::VmCallingConvention DrlVMCompilationInterface::getRuntimeHelperCallingConvention(RuntimeHelperId id) { switch(id) { case Helper_NewMultiArray: diff --git a/vm/jitrino/src/vm/drl/DrlVMInterface.h b/vm/jitrino/src/vm/drl/DrlVMInterface.h index b264c8c..6bed45c 100644 --- a/vm/jitrino/src/vm/drl/DrlVMInterface.h +++ b/vm/jitrino/src/vm/drl/DrlVMInterface.h @@ -571,18 +571,14 @@ public: // bool mayInlineObjectSynchronization(ObjectSynchronizationInfo & syncInfo); - // - // Returns the calling convention for managed code. - // - VmCallingConvention getManagedCallingConvention() { - switch (vm_managed_calling_convention()) { - case CC_Vm: - return CallingConvention_Drl; - default: - assert(0); - return (VmCallingConvention) -1; - }; - } + /** + * Returns the calling convention for managed code. + */ + VmCallingConvention getManagedCallingConvention(void); + + /** + * Returns the calling convention for the specified helper. + */ VmCallingConvention getRuntimeHelperCallingConvention(RuntimeHelperId id); bool compileMethod(MethodDesc *method); @@ -623,6 +619,7 @@ public: } private: + static VmCallingConvention toVmCC(CallingConvention cc); Type* getTypeFromDrlVMTypeHandle(Type_Info_Handle); VM_RT_SUPPORT translateHelperId(RuntimeHelperId runtimeHelperId); JIT_Handle getJitHandle() const; -- 1.3.3