|
|
@ -2,6 +2,22 @@ |
|
|
|
|
|
|
|
|
|
|
|
namespace CppSharp.Passes |
|
|
|
namespace CppSharp.Passes |
|
|
|
{ |
|
|
|
{ |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
|
|
/// This pass checks for ABI-specific details that need to be fixed
|
|
|
|
|
|
|
|
/// in the generated code.
|
|
|
|
|
|
|
|
///
|
|
|
|
|
|
|
|
/// In both the Microsoft and Itanium ABI, some functions return types
|
|
|
|
|
|
|
|
/// and parameter can be returned indirectly. In the case of an indirect
|
|
|
|
|
|
|
|
/// return type we need to add an extra pointer parameter to the function
|
|
|
|
|
|
|
|
/// and use that to call the function instead. In the case of parameters
|
|
|
|
|
|
|
|
/// then the type of that parameter is converted to a pointer.
|
|
|
|
|
|
|
|
///
|
|
|
|
|
|
|
|
/// Itanium ABI reference (3.1.4 Return values):
|
|
|
|
|
|
|
|
/// http://refspecs.linux-foundation.org/cxxabi-1.83.html#calls
|
|
|
|
|
|
|
|
///
|
|
|
|
|
|
|
|
/// Microsoft ABI reference:
|
|
|
|
|
|
|
|
/// http://blog.aaronballman.com/2012/02/describing-the-msvc-abi-for-structure-return-types/
|
|
|
|
|
|
|
|
/// </summary>
|
|
|
|
public class CheckAbiParameters : TranslationUnitPass |
|
|
|
public class CheckAbiParameters : TranslationUnitPass |
|
|
|
{ |
|
|
|
{ |
|
|
|
private readonly DriverOptions options; |
|
|
|
private readonly DriverOptions options; |
|
|
@ -11,41 +27,28 @@ namespace CppSharp.Passes |
|
|
|
this.options = options; |
|
|
|
this.options = options; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public override bool VisitMethodDecl(Method method) |
|
|
|
public override bool VisitFunctionDecl(Function function) |
|
|
|
{ |
|
|
|
{ |
|
|
|
if (!NeedsHiddenStructParameterReturn(method, options)) |
|
|
|
if (AlreadyVisited(function)) |
|
|
|
return true; |
|
|
|
return false; |
|
|
|
|
|
|
|
|
|
|
|
var structParameter = new Parameter() |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
Kind = ParameterKind.HiddenStructureReturn, |
|
|
|
|
|
|
|
QualifiedType = method.ReturnType, |
|
|
|
|
|
|
|
Name = "return", |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
method.Parameters.Insert(0, structParameter); |
|
|
|
|
|
|
|
method.ReturnType = new QualifiedType(new BuiltinType(PrimitiveType.Void)); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public static bool NeedsHiddenStructParameterReturn(Method method, DriverOptions options) |
|
|
|
if (function.IsReturnIndirect) |
|
|
|
{ |
|
|
|
{ |
|
|
|
// In both the Microsoft and Itanium ABI, functions returning
|
|
|
|
var indirectParam = new Parameter() |
|
|
|
// structure types by value have an extra parameter
|
|
|
|
{ |
|
|
|
// Itanium ABI reference (3.1.4 Return values):
|
|
|
|
Kind = ParameterKind.IndirectReturnType, |
|
|
|
// http://refspecs.linux-foundation.org/cxxabi-1.83.html#calls
|
|
|
|
QualifiedType = function.ReturnType, |
|
|
|
// Microsoft ABI reference:
|
|
|
|
Name = "return", |
|
|
|
// http://blog.aaronballman.com/2012/02/describing-the-msvc-abi-for-structure-return-types/
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
Class retClass; |
|
|
|
function.Parameters.Insert(0, indirectParam); |
|
|
|
if (!method.ReturnType.Type.IsTagDecl(out retClass)) |
|
|
|
function.ReturnType = new QualifiedType(new BuiltinType( |
|
|
|
return false; |
|
|
|
PrimitiveType.Void)); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// TODO: Add the various combinations for that need hidden parameter
|
|
|
|
// TODO: Handle indirect parameters
|
|
|
|
var needsMSHiddenPtr = options.IsMicrosoftAbi && method.IsThisCall; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return needsMSHiddenPtr || options.IsItaniumAbi; |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|