MakeParamInfo:
PUBLIC
PROCEDURE [
paramRecord: ST.TypeHandle,
paramRecordKind: ParamRecordKind,
pktSite: PktSite,
RESULTsParamInfo: ParamInfo←ParamInfoNIL,
transferType: ST.TransferTypes,
transferDeclaration: TransferDeclaration,
transferSite: TransferSite,
options: Options ]
RETURNS[paramInfo: ParamInfo] =
BEGIN
IsRESULT:
PROCEDURE [typeInfo:
ST.TypeInfo]
RETURNS[
--yes:--
BOOLEAN] =
BEGIN
RETURN[
SELECT DeterminePassingMethod [
typeInfo: typeInfo, paramKind: paramRecordKind, options: options ]
FROM
Var, Result => TRUE,
Value, Handle, InterMds => FALSE,
ENDCASE => ERROR ];
END; -- IsRESULT.
paramCount, RESULTSubCount: ParamIndex ← 0;
BEGIN
CountParams:
ST.ComponentProcedure =
BEGIN
paramCount ← componentIndex;
IF IsRESULT[
ST.GetTypeInfo[componentType]]
THEN RESULTSubCount ← RESULTSubCount + 1;
END;
[] ← ST.EnumerateRecord[recordType: paramRecord, proc: CountParams];
END;
SELECT paramRecordKind
FROM
argument => IF RESULTsParamInfo # ParamInfoNIL THEN ERROR;
result =>
IF RESULTsParamInfo = ParamInfoNIL
OR
RESULTsParamInfo.paramRecordKind # argument THEN ERROR;
ENDCASE => ERROR;
paramInfo ←
NEW[
ParamInfoObject [
1 -- The zeroth parameter is unassigned.
+ paramCount -- Explicit parameters.
+ (
IF RESULTsParamInfo=
NIL
THEN 0
ELSE RESULTsParamInfo.RESULTCount)
Implicit VARs and RESULTs in result record.
] ← [
paramRecord: paramRecord,
paramRecordKind: paramRecordKind,
pktSite: pktSite,
transferType: transferType,
transferDeclaration: transferDeclaration,
transferSite: transferSite,
options: options,
alwaysOnePkt: TRUE, alwaysMultiplePkts: FALSE,
hasOverlayParams: FALSE,
hasOverlayParamType: ALL[FALSE],
hasConversation: FALSE,
adrInfo: FalseAddressInfo,
allocInfo: NoAllocations,
sizeOf: ZeroSizeInfo,
paramCount: paramCount,
RESULTCount: RESULTSubCount,
RESULTsParamInfo: RESULTsParamInfo,
fields: NULL ]];
BEGIN
overlaySize: Words ← OverlayHeaderLength[paramInfo];
GetFieldInfo and UpdateParamInfo cooperatively maintain this variable.
minDataSize, maxDataSize: Words ← overlaySize;
GetFieldInfo:
PROCEDURE [
typeInfo: ST.TypeInfo, fieldNumber: ParamIndex,
passingMethod: ParamPassingMethod ]
RETURNS [fieldInfo: FieldInfo] =
BEGIN
location: ParamLocation;
overlayParamType: OverlayParamType ← other;
adrInfo: AddressInfo = ParamAddressInfo[
typeInfo: typeInfo,
passingMethod: passingMethod, paramKind: paramRecordKind ];
allocInfo: AllocInfo ← NoAllocations;
fieldSize: Words = Size[typeInfo.self];
minFlatSize, maxFlatSize: Words ← 0;
IF passingMethod=InterMds
AND adrInfo.hasShortPtrs
THEN Private.Warning[code: ShortInterMdsPointers, type: typeInfo.self];
IF fieldNumber=1
AND paramRecordKind=argument
AND IsConversation[typeInfo.self]
THEN location ← inConversation
ELSE
BEGIN
SELECT
TRUE
FROM
adrInfo.isStatic
AND overlaySize+fieldSize <= MaxDataSize =>
{location ← inPktOverlay; overlayParamType ← static};
adrInfo.isAddress =>
{location ← inFrame; overlayParamType ← address};
ENDCASE => {location ← inFrame};
[minFlatSize, maxFlatSize] ← MarshaledFlatSize[
type: typeInfo.self,
passingMethod: passingMethod, paramKind: paramRecordKind ];
allocInfo ← GetAllocInfo[
type: typeInfo.self,
passingMethod: passingMethod, paramKind: paramRecordKind ];
END;
RETURN[ FieldInfo [
type: typeInfo.type,
passingMethod: passingMethod,
location: location,
overlayParamType: overlayParamType,
adrInfo: adrInfo,
allocInfo: allocInfo,
size: fieldSize,
minFlatSize: minFlatSize, maxFlatSize: maxFlatSize ] ];
END; -- GetFieldInfo.
UpdateParamInfo:
PROCEDURE [
paramInfo: --VAR-- ParamInfo,
fieldInfo: FieldInfo,
staticIsError: BOOLEAN ← FALSE ] =
BEGIN OPEN adrInfo: fieldInfo.adrInfo;
IF staticIsError AND adrInfo.isStatic THEN ERROR;
SELECT fieldInfo.location
FROM
inConversation => paramInfo.hasConversation ← TRUE;
inPktOverlay, inFrameAndOverlay =>
BEGIN
paramInfo.hasOverlayParams ← TRUE;
paramInfo.hasOverlayParamType[fieldInfo.overlayParamType] ← TRUE;
overlaySize ← overlaySize + fieldInfo.size;
IF overlaySize > MaxDataSize THEN ERROR;
END;
inFrame, inStream => NULL;
ENDCASE => ERROR;
IF adrInfo.isAddress OR adrInfo.isTransfer
THEN BEGIN
Don't send the addresses of top-level AC params, just the referents.
minDataSize ← minDataSize + fieldInfo.minFlatSize - fieldInfo.size;
maxDataSize ← maxDataSize + fieldInfo.maxFlatSize - fieldInfo.size;
END
ELSE BEGIN
minDataSize ← minDataSize + fieldInfo.minFlatSize;
maxDataSize ← maxDataSize + fieldInfo.maxFlatSize;
END;
paramInfo.allocInfo ← AddAllocInfo[paramInfo.allocInfo, fieldInfo.allocInfo];
paramInfo.adrInfo ← AddressInfo[
hasStatics: adrInfo.hasStatics OR paramInfo.adrInfo.hasStatics,
hasAddresses: adrInfo.hasAddresses OR paramInfo.adrInfo.hasAddresses,
hasDynamics: adrInfo.hasDynamics OR paramInfo.adrInfo.hasDynamics,
hasTransfers: adrInfo.hasTransfers OR paramInfo.adrInfo.hasTransfers,
hasGC: adrInfo.hasGC OR paramInfo.adrInfo.hasGC,
hasHeap: adrInfo.hasHeap OR paramInfo.adrInfo.hasHeap,
hasMds: adrInfo.hasMds OR paramInfo.adrInfo.hasMds,
hasShortPtrs: adrInfo.hasShortPtrs OR paramInfo.adrInfo.hasShortPtrs ];
END; -- UpdateParamInfo.
IF paramCount > 0
THEN
BEGIN
ComputeFieldInfo:
ST.ComponentProcedure =
BEGIN
typeInfo: ST.TypeInfo = ST.GetTypeInfo[componentType];
passingMethod: ParamPassingMethod = DeterminePassingMethod[
typeInfo: typeInfo, paramKind: paramRecordKind, options: options,
reportErrors: TRUE ];
fieldInfo: FieldInfo = GetFieldInfo[typeInfo, componentIndex, passingMethod];
paramInfo.fields[componentIndex] ← fieldInfo;
UpdateParamInfo[paramInfo, fieldInfo];
END; -- ComputeFieldInfo.
[] ← ST.EnumerateRecord[recordType: paramRecord, proc: ComputeFieldInfo];
END; -- Of parameter record processing.
IF paramRecordKind=result
AND RESULTsParamInfo.RESULTCount > 0
THEN
BEGIN
resultIndex: ParamIndex ← paramCount;
ComputeResultInfo: ParamProcedure =
BEGIN
SELECT paramFieldInfo.passingMethod
FROM
Var, Result =>
BEGIN
resultFieldInfo: FieldInfo = GetFieldInfo[
ST.GetTypeInfo[paramType], paramIndex, paramFieldInfo.passingMethod ];
paramInfo.fields[(resultIndex←resultIndex+1)] ← resultFieldInfo;
UpdateParamInfo[paramInfo, resultFieldInfo];
END;
ENDCASE => NULL;
END; -- ComputeResultInfo.
Marshal.EnumerateParams[
paramInfo: RESULTsParamInfo, paramProc: ComputeResultInfo ];
IF resultIndex # paramCount+RESULTsParamInfo.RESULTCount THEN ERROR;
END; -- Of implicit results processing.
paramInfo.sizeOf ← [
overlayHeader: OverlayHeaderLength[paramInfo],
overlayParamRecord: overlaySize,
pktToAllocate:
IF paramInfo.adrInfo.hasDynamics
THEN MaxDataSize ELSE MIN[MaxDataSize, maxDataSize] ];
paramInfo.alwaysOnePkt ←
~paramInfo.adrInfo.hasDynamics AND maxDataSize <= MaxDataSize;
paramInfo.alwaysMultiplePkts ← minDataSize > MaxDataSize;
END;
RETURN[--READONLY-- paramInfo];
END;
EnumerateParams:
PUBLIC
PROCEDURE [
paramInfo: ParamInfo,
paramProc: ParamProcedure,
includeRESULTs: BOOLEAN←FALSE ] =
BEGIN
This enumerator is in this module because it cooperates intimately
with MakeParamInfo in the handling of VAR and RESULT parameters.
resultInfo: ParamInfo = paramInfo.RESULTsParamInfo;
IF paramInfo.paramCount > 0
THEN
BEGIN
DoParam:
ST.ComponentProcedure =
BEGIN
RETURN[
stop: paramProc[
paramName: component,
paramType: componentType,
paramIndex: componentIndex,
paramFieldInfo: paramInfo.fields[componentIndex]].stop ];
END; -- DoParam.
[] ← ST.EnumerateRecord[recordType: paramInfo.paramRecord, proc: DoParam];
END;
IF includeRESULTs
AND
paramInfo.paramRecordKind=result AND resultInfo.RESULTCount > 0
THEN
BEGIN
resultIndex: ParamIndex ← paramInfo.paramCount;
DoParam: ParamProcedure =
BEGIN
SELECT paramFieldInfo.passingMethod
FROM
Var, Result =>
RETURN[
stop: paramProc[
paramName: paramName,
paramType: paramType,
paramIndex: paramIndex,
paramFieldInfo:
paramInfo.fields[(resultIndex←resultIndex+1)]].stop ];
ENDCASE => NULL;
END; -- DoParam.
EnumerateParams[resultInfo, DoParam];
END;
END;