Skip to content

Commit 0636196

Browse files
authored
Merge pull request #328 from esa/OPTIMIZE_RT2
Optimize Code Generation by eliminating Unused Functions
2 parents 3758af1 + 69d540f commit 0636196

File tree

14 files changed

+394
-99
lines changed

14 files changed

+394
-99
lines changed

BackendAst/DAstACN.fs

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -330,7 +330,14 @@ let private createAcnFunction (r: Asn1AcnAst.AstRoot)
330330

331331
let errCodStr = errCodes |> List.map(fun x -> EmitTypeAssignment_def_err_code x.errCodeName (BigInteger x.errCodeValue) x.comment) |> List.distinct
332332
let funcDef = Some(EmitTypeAssignment_primitive_def varName sStar funcName (typeDefinition.longTypedefName2 lm.lg.hasModules) errCodStr (t.acnMaxSizeInBits = 0I) nMaxBytesInACN ( t.acnMaxSizeInBits) prms soSparkAnnotations codec)
333-
func, funcDef, auxiliaries, icdResult, ns1a
333+
let ns2a =
334+
match t.id.topLevelTas with
335+
| None -> ns1a
336+
| Some tasInfo ->
337+
let caller = {Caller.typeId = tasInfo; funcType= UperEncDecFunctionType}
338+
let callee = {Callee.typeId = tasInfo; funcType=IsValidFunctionType}
339+
addFunctionCallToState ns1a caller callee
340+
func, funcDef, auxiliaries, icdResult, ns2a
334341

335342
let icdAux, ns3 =
336343
match icdResult with
@@ -2523,9 +2530,20 @@ let createReferenceFunction (r:Asn1AcnAst.AstRoot) (deps:Asn1AcnAst.AcnInsertedF
25232530
let funcBodyContent = callBaseTypeFunc lm pp baseFncName codec
25242531
Some ({AcnFuncBodyResult.funcBody = funcBodyContent; errCodes = [errCode]; localVariables = []; bValIsUnReferenced= false; bBsIsUnReferenced=false; resultExpr=resultExpr; auxiliaries=[]; icdResult = icd}), us)
25252532

2533+
let ns =
2534+
match t.id.topLevelTas with
2535+
| None -> us
2536+
| Some tasInfo ->
2537+
let caller = {Caller.typeId = tasInfo; funcType=AcnEncDecFunctionType}
2538+
//match List.rev t.referencedBy with
2539+
//| [] -> {Caller.typeId = tasInfo; funcType=AcnEncDecFunctionType}
2540+
//| hd::_ -> {Caller.typeId = {TypeAssignmentInfo.modName = hd.modName; tasName=hd.tasName}; funcType=AcnEncDecFunctionType}
2541+
2542+
let callee = {Callee.typeId = {TypeAssignmentInfo.modName = o.modName.Value; tasName=o.tasName.Value} ; funcType=AcnEncDecFunctionType}
2543+
addFunctionCallToState us caller callee
25262544

25272545
let soSparkAnnotations = Some(sparkAnnotations lm (typeDefinition.longTypedefName2 lm.lg.hasModules) codec)
2528-
let a, ns = createAcnFunction r deps lm codec t typeDefinition isValidFunc funcBody (fun atc -> true) soSparkAnnotations [] us
2546+
let a, ns = createAcnFunction r deps lm codec t typeDefinition isValidFunc funcBody (fun atc -> true) soSparkAnnotations [] ns
25292547
Some a, ns
25302548

25312549
| Some encOptions ->

BackendAst/DAstConstruction.fs

Lines changed: 198 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -729,9 +729,9 @@ let private createChoiceChild (r:Asn1AcnAst.AstRoot) (lm:LanguageMacros) (m:Asn
729729
let private createReferenceType (r:Asn1AcnAst.AstRoot) (deps:Asn1AcnAst.AcnInsertedFieldDependencies) (lm:LanguageMacros) (m:Asn1AcnAst.Asn1Module) (pi : Asn1Fold.ParentInfo<ParentInfoData> option) (t:Asn1AcnAst.Asn1Type) (o:Asn1AcnAst.ReferenceType) (newResolvedType:Asn1Type, us:State) =
730730
let newPrms, us0 = t.acnParameters |> foldMap(fun ns p -> mapAcnParameter r deps lm m t p ns) us
731731
let defOrRef = lm.lg.definitionOrRef o.definitionOrRef
732-
let equalFunction = DAstEqual.createReferenceTypeEqualFunction r lm t o defOrRef newResolvedType
733-
let initFunction = DAstInitialize.createReferenceType r lm t o defOrRef newResolvedType
734-
let isValidFunction, s1 = DastValidate2.createReferenceTypeFunction r lm t o defOrRef newResolvedType us
732+
let equalFunction, s00 = DAstEqual.createReferenceTypeEqualFunction r lm t o defOrRef newResolvedType us
733+
let initFunction,s0 = DAstInitialize.createReferenceType r lm t o defOrRef newResolvedType s00
734+
let isValidFunction, s1 = DastValidate2.createReferenceTypeFunction r lm t o defOrRef newResolvedType s0
735735
let uperEncFunction, s2 = DAstUPer.createReferenceFunction r lm Codec.Encode t o defOrRef isValidFunction newResolvedType s1
736736
let uperDecFunction, s3 = DAstUPer.createReferenceFunction r lm Codec.Decode t o defOrRef isValidFunction newResolvedType s2
737737
let acnEncFunction, s4 = DAstACN.createReferenceFunction r deps lm Codec.Encode t o defOrRef isValidFunction newResolvedType s3
@@ -782,6 +782,7 @@ let private createType (r:Asn1AcnAst.AstRoot) pi (t:Asn1AcnAst.Asn1Type) ((newKi
782782
inheritInfo = t.inheritInfo
783783
typeAssignmentInfo = t.typeAssignmentInfo
784784
unitsOfMeasure = t.unitsOfMeasure
785+
referencedBy = t.referencedBy
785786
//newTypeDefName = DAstTypeDefinition2.getTypedefName r pi t
786787
}
787788
match us.newTypesMap.ContainsKey t.id with
@@ -1000,41 +1001,203 @@ let private mapFile (r:Asn1AcnAst.AstRoot) (newTasMap : Map<TypeAssignmentInfo,
10001001
let private reMapFile (r:Asn1AcnAst.AstRoot) (icdStgFileName:string) (files0:Asn1File list) (deps:Asn1AcnAst.AcnInsertedFieldDependencies) (lm:LanguageMacros) (f:Asn1File) (us:State) =
10011002
let newModules, ns = f.Modules |> foldMap (fun cs m -> reMapModule r icdStgFileName files0 deps lm m cs) us
10021003
{f with Modules = newModules}, ns
1003-
(*
1004-
//the following functions determines which functions are used by PDU types.
1005-
//Only those functions are generated in the generated code.
1006-
let determinGeneratedFunctions (r:Asn1AcnAst.AstRoot) (files: Asn1File list) (us:State) =
1007-
let getFunctionCalls (tasId:ReferenceToType)=
1004+
1005+
let detectPDUs2 (r:Asn1AcnAst.AstRoot) =
1006+
let callesMap =
1007+
r.allDependencies |>
1008+
List.groupBy(fun (a,_) -> a) |> //group by caller
1009+
List.map(fun (a,b) -> a, b |> List.map snd |> List.distinct) |> //remove duplicates
1010+
Map.ofList
1011+
1012+
let callesSet =
1013+
r.allDependencies |>
1014+
List.map(fun (caller, callee) -> callee) |>
1015+
Set.ofList
1016+
1017+
let rec getCallesCount (tsInfo:TypeAssignmentInfo) =
1018+
match callesMap.TryFind tsInfo with
1019+
| None -> 0
1020+
| Some l ->
1021+
let l1 = l.Length
1022+
let l2 = l |> List.map getCallesCount |> List.sum
1023+
l1 + l2
1024+
1025+
//PDUS are the types that are not called by any other types
1026+
let pdus =
1027+
seq {
1028+
for f in r.Files do
1029+
for m in f.Modules do
1030+
for tas in m.TypeAssignments do
1031+
let tsInfo = {TypeAssignmentInfo.modName = m.Name.Value; tasName = tas.Name.Value}
1032+
if not (callesSet.Contains tsInfo) then
1033+
yield (tsInfo, getCallesCount tsInfo)
1034+
} |> Seq.toList
1035+
1036+
let pudsSorted = pdus |> List.sortByDescending(fun (tas, callesCnt) -> callesCnt)
1037+
let maxToPrint = min 100 (pudsSorted.Length)
1038+
printfn "PDUs detected: %d. Printing the first %d" pudsSorted.Length maxToPrint
1039+
for (tas, callesCnt) in pudsSorted |> List.take maxToPrint do
1040+
printfn "%s.%s references %d types" tas.modName tas.tasName callesCnt
1041+
1042+
let detectPDUs (r:Asn1AcnAst.AstRoot) (us:State) =
1043+
let functionTypes = Set.ofList [AcnEncDecFunctionType]
1044+
let functionCalls = us.functionCalls |> Map.filter(fun z _ -> z.funcType = AcnEncDecFunctionType)
1045+
printfn "Detecting PDUs. Function calls: %d" functionCalls.Count
1046+
1047+
//print all calls
1048+
printfn "== Calls detected =="
1049+
functionCalls |> Seq.iter(fun fc ->
1050+
let calleesStr = sprintf "%s.%s" fc.Key.typeId.modName fc.Key.typeId.tasName
1051+
let callees = fc.Value |> List.map(fun c -> c.typeId) |> List.distinct |> List.map(fun z -> sprintf "%s.%s" z.modName z.tasName) |> Seq.StrJoin ", "
1052+
printfn "%s calls %s" calleesStr callees)
1053+
printfn "== End of calls =="
1054+
1055+
let memo = System.Collections.Generic.Dictionary<Caller, Set<Caller> >()
1056+
let rec getCallees2 bIsTass (c: Caller) =
1057+
let getCallees2_aux (c: Caller) =
1058+
if memo.ContainsKey(c) then
1059+
memo.[c]
1060+
else
1061+
let result =
1062+
match functionCalls.ContainsKey(c) with
1063+
| false ->
1064+
match bIsTass with
1065+
| true -> Set.empty
1066+
| false -> Set.singleton c
1067+
| true ->
1068+
let callees = functionCalls.[c]
1069+
let ret2 =
1070+
callees
1071+
|> List.map (fun callee -> getCallees2 false {Caller.typeId = callee.typeId; funcType = callee.funcType})
1072+
|> List.fold Set.union Set.empty
1073+
match bIsTass with
1074+
| true -> ret2
1075+
| false -> Set.add c ret2
1076+
memo.[c] <- result
1077+
result
1078+
getCallees2_aux c
1079+
1080+
let callesList =
10081081
seq {
1009-
for c in us.functionCalls do
1010-
if c.Key.typeId.AsString.StartsWith (tasId.AsString) then
1011-
yield (c.Key, c.Value)
1082+
for f in r.Files do
1083+
for m in f.Modules do
1084+
for tas in m.TypeAssignments do
1085+
for fncType in functionTypes do
1086+
//let msg = sprintf "Processing %s.%s. " m.Name.Value tas.Name.Value
1087+
//printf "%s" msg
1088+
let tsInfo = {TypeAssignmentInfo.modName = m.Name.Value; tasName = tas.Name.Value}
1089+
let caller = {Caller.typeId = tsInfo; funcType = fncType}
1090+
//let calles = getCallees true caller |> List.map(fun c -> c.typeId) |> List.distinct
1091+
if tas.Name.Value = "Observable-Event" then
1092+
printfn "debug"
1093+
let calles = getCallees2 true caller |> Set.map(fun c -> c.typeId)
1094+
//printfn "Calles detected: %d" calles.Length
1095+
yield calles
10121096
} |> Seq.toList
1097+
printfn "Calles detected: %d" callesList.Length
1098+
//let callesMap = callesList |> List.collect id |> List.distinct |> Set.ofList
1099+
let callesMap = callesList |> List.fold (fun acc x -> Set.union acc x) Set.empty
10131100

1014-
let allTasses =
1101+
//PDUS are the types that are not called by any other types
1102+
let pdus =
10151103
seq {
1016-
for f in files do
1104+
for f in r.Files do
10171105
for m in f.Modules do
10181106
for tas in m.TypeAssignments do
1019-
match tas.Type.isValidFunction with
1020-
| None -> ()
1021-
| Some isValidFunction ->
1022-
match isValidFunction.funcName with
1023-
| None -> ()
1024-
| Some fncName ->
1025-
let fncCalls = getFunctionCalls tas.Type.id
1026-
yield {modName = m.Name.Value; tasName = tas.Name.Value; validationFunName = fncName; validationDependencies = fncCalls}
1027-
1028-
} |> List.ofSeq
1029-
let ret =
1030-
match r.args.icdPdus with
1031-
| None -> allTasses |> List.map(fun tas -> tas.modName, tas.tasName)
1032-
| Some pdus ->
1033-
let pduTas = pdus |> List.choose (fun pdu -> allTasses |> List.tryFind(fun tas -> tas.tasName = pdu))
1034-
0
1035-
0
1036-
1037-
*)
1107+
let tsInfo = {TypeAssignmentInfo.modName = m.Name.Value; tasName = tas.Name.Value}
1108+
if not (callesMap.Contains tsInfo) then
1109+
//printfn "PDU detected: %s.%s" m.Name.Value tas.Name.Value
1110+
let caller = {Caller.typeId = tsInfo; funcType = AcnEncDecFunctionType}
1111+
//let calles = getCallees true caller |> List.map(fun c -> c.typeId) |> List.distinct
1112+
let calles = getCallees2 true caller |> Set.map(fun c -> c.typeId)
1113+
yield (tsInfo, calles)
1114+
} |> Seq.toList
1115+
1116+
let pudsSorted = pdus |> List.sortByDescending(fun (tas, calles) -> calles.Count)
1117+
let maxToPrint = min 100 (pudsSorted.Length)
1118+
printfn "PDUs detected: %d. Printing the first %d" pudsSorted.Length maxToPrint
1119+
for (tas, calles) in pudsSorted |> List.take maxToPrint do
1120+
printfn "%s.%s references %d types" tas.modName tas.tasName calles.Count
1121+
1122+
let calculateFunctionToBeGenerated (r:Asn1AcnAst.AstRoot) (us:State) =
1123+
let functionCalls = us.functionCalls
1124+
let requiresUPER = r.args.encodings |> Seq.exists ( (=) Asn1Encoding.UPER)
1125+
let requiresAcn = r.args.encodings |> Seq.exists ( (=) Asn1Encoding.ACN)
1126+
1127+
let functionTypes =
1128+
seq {
1129+
yield InitFunctionType;
1130+
yield IsValidFunctionType;
1131+
if r.args.GenerateEqualFunctions then yield EqualFunctionType;
1132+
if requiresUPER then yield UperEncDecFunctionType;
1133+
if requiresAcn then yield AcnEncDecFunctionType;
1134+
} |> Seq.toList
1135+
1136+
(*
1137+
let rec getCallees (c: Caller)=
1138+
seq {
1139+
yield c
1140+
match functionCalls.ContainsKey c with
1141+
| false -> ()
1142+
| true ->
1143+
let callees = functionCalls[c]
1144+
for callee in callees do
1145+
yield! getCallees {Caller.typeId = callee.typeId; funcType = callee.funcType}
1146+
} |> Seq.toList
1147+
*)
1148+
let memo2 = System.Collections.Generic.Dictionary<Caller, Set<Caller> >()
1149+
let rec getCallees (c: Caller)=
1150+
if memo2.Count%50 = 0 then printfn "Processing %d" memo2.Count
1151+
match memo2.ContainsKey(c) with
1152+
| true -> memo2.[c]
1153+
| false ->
1154+
let getCallees_aux (c: Caller) =
1155+
let result =
1156+
match functionCalls.ContainsKey c with
1157+
| false -> Set.singleton c
1158+
| true ->
1159+
let callees = functionCalls[c]
1160+
let ret2 =
1161+
callees
1162+
|> List.map (fun callee -> getCallees {Caller.typeId = callee.typeId; funcType = callee.funcType})
1163+
|> List.fold Set.union Set.empty
1164+
Set.add c ret2
1165+
memo2.[c] <- result
1166+
result
1167+
getCallees_aux c
1168+
1169+
let ret =
1170+
seq {
1171+
for f in r.Files do
1172+
for m in f.Modules do
1173+
let tasToGenerate, bFindCalles =
1174+
match r.args.icdPdus with
1175+
| None -> m.TypeAssignments, false
1176+
| Some pdus -> pdus |> List.choose (fun pdu -> m.TypeAssignments |> List.tryFind(fun tas -> tas.Name.Value = pdu)), true
1177+
for tas in tasToGenerate do
1178+
for fncType in functionTypes do
1179+
let tsInfo = {TypeAssignmentInfo.modName = m.Name.Value; tasName = tas.Name.Value}
1180+
let caller = {Caller.typeId = tsInfo; funcType = fncType}
1181+
match bFindCalles with
1182+
| true -> yield! getCallees caller
1183+
| false -> yield caller
1184+
} |> Set.ofSeq
1185+
printfn "Function calls detected: %d" ret.Count
1186+
match r.args.icdPdus with
1187+
| None -> ()
1188+
| Some _ ->
1189+
//let's print in the console the functions that will not be generated
1190+
let s = ret
1191+
for f in r.Files do
1192+
for m in f.Modules do
1193+
for tas in m.TypeAssignments do
1194+
for fncType in functionTypes do
1195+
let tsInfo = {TypeAssignmentInfo.modName = m.Name.Value; tasName = tas.Name.Value}
1196+
let caller = {Caller.typeId = tsInfo; funcType = fncType}
1197+
if not (s.Contains caller) then
1198+
printfn "Function %A will not be generated for %s.%s" fncType tsInfo.modName tsInfo.tasName
1199+
1200+
ret
10381201

10391202
let DoWork (r:Asn1AcnAst.AstRoot) (icdStgFileName:string) (deps:Asn1AcnAst.AcnInsertedFieldDependencies) (lang:CommonTypes.ProgrammingLanguage) (lm:LanguageMacros) (encodings: CommonTypes.Asn1Encoding list) : AstRoot=
10401203
let l = lang
@@ -1063,6 +1226,8 @@ let DoWork (r:Asn1AcnAst.AstRoot) (icdStgFileName:string) (deps:Asn1AcnAst.AcnIn
10631226
let files0, ns = TL "mapFile" (fun () -> r.Files |> foldMap (fun cs f -> mapFile r newTasMap icdStgFileName deps lm f cs) ns0)
10641227
let files, ns = TL "reMapFile" (fun () -> files0 |> foldMap (fun cs f -> reMapFile r icdStgFileName files0 deps lm f cs) ns)
10651228
let icdTases = ns.icdHashes
1229+
if r.args.detectPdus then
1230+
detectPDUs2 r //this function will print the PDUs detected
10661231
{
10671232
AstRoot.Files = files
10681233
acnConstants = r.acnConstants
@@ -1072,4 +1237,5 @@ let DoWork (r:Asn1AcnAst.AstRoot) (icdStgFileName:string) (deps:Asn1AcnAst.AcnIn
10721237
acnParseResults = r.acnParseResults
10731238
deps = deps
10741239
icdHashes = ns.icdHashes
1240+
callersSet = calculateFunctionToBeGenerated r ns
10751241
}

BackendAst/DAstEqual.fs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,7 @@ let createChoiceEqualFunction (r:Asn1AcnAst.AstRoot) (lm:LanguageMacros) (t:Asn1
285285
createEqualFunction_any r lm t typeDefinition (EqualBodyStatementList isEqualBody)
286286
//createCompositeEqualFunction r l lm t typeDefinition isEqualBody (stgMacroCompDefFunc l)
287287

288-
let createReferenceTypeEqualFunction (r:Asn1AcnAst.AstRoot) (lm:LanguageMacros) (t:Asn1AcnAst.Asn1Type) (o:Asn1AcnAst.ReferenceType) (defOrRef:TypeDefinitionOrReference) (baseType:Asn1Type) =
288+
let createReferenceTypeEqualFunction (r:Asn1AcnAst.AstRoot) (lm:LanguageMacros) (t:Asn1AcnAst.Asn1Type) (o:Asn1AcnAst.ReferenceType) (defOrRef:TypeDefinitionOrReference) (baseType:Asn1Type) (us:State) =
289289
//let isEqualFuncName = getEqualFuncName r l lm t.id
290290
let isEqualFuncName = getFuncName r lm defOrRef
291291
let typeDefinitionName = lm.lg.getLongTypedefName defOrRef
@@ -327,7 +327,7 @@ let createReferenceTypeEqualFunction (r:Asn1AcnAst.AstRoot) (lm:LanguageMacros)
327327
| IA5String _
328328
| ReferenceType _ ->
329329
let bs = baseType.equalFunction
330-
createEqualFunction_any r lm t defOrRef bs.isEqualBody
330+
createEqualFunction_any r lm t defOrRef bs.isEqualBody, us
331331
| OctetString _
332332
| BitString _
333333
| ObjectIdentifier _
@@ -343,6 +343,15 @@ let createReferenceTypeEqualFunction (r:Asn1AcnAst.AstRoot) (lm:LanguageMacros)
343343
let val2 = lm.lg.getParamTypeSuffix t "2" CommonTypes.Codec.Encode
344344

345345
let stgMacroDefFunc = lm.equal.PrintEqualDefinitionComposite
346+
let ns =
347+
match t.id.topLevelTas with
348+
| None ->
349+
//printfn "No type assignment info for %A" t.id
350+
us
351+
| Some tasInfo ->
352+
let caller = {Caller.typeId = tasInfo; funcType=EqualFunctionType}
353+
let callee = {Callee.typeId = {TypeAssignmentInfo.modName = o.modName.Value; tasName=o.tasName.Value} ; funcType=EqualFunctionType}
354+
addFunctionCallToState us caller callee
346355

347356
let isEqualFunc, isEqualFuncDef =
348357
match isEqualFuncName with
@@ -358,5 +367,5 @@ let createReferenceTypeEqualFunction (r:Asn1AcnAst.AstRoot) (lm:LanguageMacros)
358367
isEqualBody = EqualBodyStatementList (isEqualBody )
359368
isEqualFunc = isEqualFunc
360369
isEqualFuncDef = isEqualFuncDef
361-
}
370+
}, ns
362371

0 commit comments

Comments
 (0)