public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [Patch] BaseTools: Enhance parse performance by optimize ValueExpressionEx
@ 2018-01-26 16:28 Yonghong Zhu
  2018-01-26 19:20 ` Andrew Fish
  0 siblings, 1 reply; 3+ messages in thread
From: Yonghong Zhu @ 2018-01-26 16:28 UTC (permalink / raw)
  To: edk2-devel; +Cc: Yunhua Feng, Liming Gao

From: Yunhua Feng <yunhuax.feng@intel.com>

Optimize ValueExpressionEx function to enhance meta-data file parse
performance.

Cc: Liming Gao <liming.gao@intel.com>
Cc: Yonghong Zhu <yonghong.zhu@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Yunhua Feng <yunhuax.feng@intel.com>
---
 BaseTools/Source/Python/AutoGen/AutoGen.py         |  16 +-
 BaseTools/Source/Python/Common/Expression.py       | 286 +++++++++++----------
 BaseTools/Source/Python/Workspace/DscBuildData.py  |  19 +-
 .../Source/Python/Workspace/MetaFileParser.py      |   8 -
 BaseTools/Source/Python/build/BuildReport.py       |   9 +-
 5 files changed, 167 insertions(+), 171 deletions(-)

diff --git a/BaseTools/Source/Python/AutoGen/AutoGen.py b/BaseTools/Source/Python/AutoGen/AutoGen.py
index ab178c9..1cf50e8 100644
--- a/BaseTools/Source/Python/AutoGen/AutoGen.py
+++ b/BaseTools/Source/Python/AutoGen/AutoGen.py
@@ -1243,10 +1243,11 @@ class PlatformAutoGen(AutoGen):
         self.FvTargetList = self.Workspace.FvTargetList
         self.AllPcdList = []
         # get the original module/package/platform objects
         self.BuildDatabase = Workspace.BuildDatabase
         self.DscBuildDataObj = Workspace.Platform
+        self._GuidDict = Workspace._GuidDict
 
         # flag indicating if the makefile/C-code file has been created or not
         self.IsMakeFileCreated  = False
         self.IsCodeFileCreated  = False
 
@@ -2461,26 +2462,13 @@ class PlatformAutoGen(AutoGen):
             if FromPcd.DatumType not in [None, '']:
                 ToPcd.DatumType = FromPcd.DatumType
             if FromPcd.SkuInfoList not in [None, '', []]:
                 ToPcd.SkuInfoList = FromPcd.SkuInfoList
             # Add Flexible PCD format parse
-            PcdValue = ToPcd.DefaultValue
-            if PcdValue:
-                try:
-                    ToPcd.DefaultValue = ValueExpression(PcdValue)(True)
-                except WrnExpression, Value:
-                    ToPcd.DefaultValue = Value.result
-                except BadExpression, Value:
-                    EdkLogger.error('Parser', FORMAT_INVALID, 'PCD [%s.%s] Value "%s", %s' %(ToPcd.TokenSpaceGuidCName, ToPcd.TokenCName, ToPcd.DefaultValue, Value),
-                                    File=self.MetaFile)
             if ToPcd.DefaultValue:
-                _GuidDict = {}
-                for Pkg in self.PackageList:
-                    Guids = Pkg.Guids
-                    _GuidDict.update(Guids)
                 try:
-                    ToPcd.DefaultValue = ValueExpressionEx(ToPcd.DefaultValue, ToPcd.DatumType, _GuidDict)(True)
+                    ToPcd.DefaultValue = ValueExpressionEx(ToPcd.DefaultValue, ToPcd.DatumType, self._GuidDict)(True)
                 except BadExpression, Value:
                     EdkLogger.error('Parser', FORMAT_INVALID, 'PCD [%s.%s] Value "%s", %s' %(ToPcd.TokenSpaceGuidCName, ToPcd.TokenCName, ToPcd.DefaultValue, Value),
                                         File=self.MetaFile)
 
             # check the validation of datum
diff --git a/BaseTools/Source/Python/Common/Expression.py b/BaseTools/Source/Python/Common/Expression.py
index 55fa06d..d62fb48 100644
--- a/BaseTools/Source/Python/Common/Expression.py
+++ b/BaseTools/Source/Python/Common/Expression.py
@@ -1,9 +1,9 @@
 ## @file
 # This file is used to parse and evaluate expression in directive or PCD value.
 #
-# Copyright (c) 2011 - 2017, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>
 # This program and the accompanying materials
 # are licensed and made available under the terms and conditions of the BSD License
 # which accompanies this distribution.    The full text of the license may be found at
 # http://opensource.org/licenses/bsd-license.php
 #
@@ -249,13 +249,10 @@ class ValueExpression(object):
         self._NoProcess = False
         if type(Expression) != type(''):
             self._Expr = Expression
             self._NoProcess = True
             return
-        if Expression.strip().startswith('{') and Expression.strip().endswith('}'):
-            self._Expr = Expression
-            self._NoProcess = True
 
         self._Expr = ReplaceExprMacro(Expression.strip(),
                                   SymbolTable,
                                   SupportedInMacroList)
 
@@ -291,17 +288,19 @@ class ValueExpression(object):
         self._Expr = self._Expr.strip()
         if RealValue and Depth == 0:
             self._Token = self._Expr
             if self.__IsNumberToken():
                 return self._Expr
-
+            Token = ''
             try:
                 Token = self._GetToken()
-                if type(Token) == type('') and Token.startswith('{') and Token.endswith('}') and self._Idx >= self._Len:
-                    return self._Expr
             except BadExpression:
                 pass
+            if type(Token) == type('') and Token.startswith('{') and Token.endswith('}') and self._Idx >= self._Len:
+                if len(Token) != len(self._Expr.replace(' ', '')):
+                    raise BadExpression
+                return self._Expr
 
             self._Idx = 0
             self._Token = ''
 
         Val = self._ConExpr()
@@ -591,15 +590,14 @@ class ValueExpression(object):
             self._LiteralToken.endswith('}'):
             return True
 
         if self.HexPattern.match(self._LiteralToken):
             Token = self._LiteralToken[2:]
-            Token = Token.lstrip('0')
             if not Token:
                 self._LiteralToken = '0x0'
             else:
-                self._LiteralToken = '0x' + Token.lower()
+                self._LiteralToken = '0x' + Token
             return True
         return False
 
     def _GetToken(self):
         return self.__GetNList()
@@ -734,147 +732,155 @@ class ValueExpressionEx(ValueExpression):
         PcdValue = self.PcdValue
         try:
             PcdValue = ValueExpression.__call__(self, RealValue, Depth)
         except WrnExpression, Value:
             PcdValue = Value.result
-
-        if PcdValue == 'True':
-            PcdValue = '1'
-        if PcdValue == 'False':
-            PcdValue = '0'
-        if self.PcdType in ['UINT8', 'UINT16', 'UINT32', 'UINT64', 'BOOLEAN']:
-            PcdValue = PcdValue.strip()
-            if type(PcdValue) == type('') and PcdValue.startswith('{') and PcdValue.endswith('}'):
-                PcdValue = PcdValue[1:-1].split(',')
-            if type(PcdValue) == type([]):
-                TmpValue = 0
-                Size = 0
-                for Item in PcdValue:
-                    if Item.startswith('UINT16'):
-                        ItemSize = 2
-                    elif Item.startswith('UINT32'):
-                        ItemSize = 4
-                    elif Item.startswith('UINT64'):
-                        ItemSize = 8
-                    else:
-                        ItemSize = 0
-                    Item = ValueExpressionEx(Item, self.PcdType, self._Symb)(True)
-
-                    if ItemSize == 0:
-                        ItemValue, ItemSize = ParseFieldValue(Item)
-                    else:
-                        ItemValue = ParseFieldValue(Item)[0]
-
-                    if type(ItemValue) == type(''):
-                        ItemValue = int(ItemValue, 16) if ItemValue.startswith('0x') else int(ItemValue)
-
-                    TmpValue = (ItemValue << (Size * 8)) | TmpValue
-                    Size = Size + ItemSize
-            else:
-                TmpValue, Size = ParseFieldValue(PcdValue)
-            if type(TmpValue) == type(''):
-                TmpValue = int(TmpValue)
-            else:
-                PcdValue = '0x%0{}X'.format(Size) % (TmpValue)
-            if TmpValue < 0:
-                raise  BadExpression('Type %s PCD Value is negative' % self.PcdType)
-            if self.PcdType == 'UINT8' and Size > 1:
-                raise BadExpression('Type %s PCD Value Size is Larger than 1 byte' % self.PcdType)
-            if self.PcdType == 'UINT16' and Size > 2:
-                raise BadExpression('Type %s PCD Value Size is Larger than 2 byte' % self.PcdType)
-            if self.PcdType == 'UINT32' and Size > 4:
-                raise BadExpression('Type %s PCD Value Size is Larger than 4 byte' % self.PcdType)
-            if self.PcdType == 'UINT64' and Size > 8:
-                raise BadExpression('Type %s PCD Value Size is Larger than 8 byte' % self.PcdType)
-        if self.PcdType in ['VOID*']:
-            try:
-                TmpValue = long(PcdValue)
-                TmpList = []
-                if TmpValue.bit_length() == 0:
-                    PcdValue = '{0x00}'
-                else:
-                    for I in range((TmpValue.bit_length() + 7) / 8):
-                        TmpList.append('0x%02x' % ((TmpValue >> I * 8) & 0xff))
-                    PcdValue = '{' + ', '.join(TmpList) + '}'
-            except:
-                if PcdValue.strip().startswith('{'):
-                    PcdValue = PcdValue.strip()[1:-1].strip()
+        except BadExpression:
+            if self.PcdType in ['UINT8', 'UINT16', 'UINT32', 'UINT64', 'BOOLEAN']:
+                PcdValue = PcdValue.strip()
+                if type(PcdValue) == type('') and PcdValue.startswith('{') and PcdValue.endswith('}'):
+                    PcdValue = PcdValue[1:-1].split(',')
+                if type(PcdValue) == type([]):
+                    TmpValue = 0
                     Size = 0
-                    ValueStr = ''
-                    TokenSpaceGuidName = ''
-                    if PcdValue.startswith('GUID') and PcdValue.endswith(')'):
-                        try:
-                            TokenSpaceGuidName = re.search('GUID\((\w+)\)', PcdValue).group(1)
-                        except:
-                            pass
-                        if TokenSpaceGuidName and TokenSpaceGuidName in self._Symb:
-                            PcdValue = 'GUID(' + self._Symb[TokenSpaceGuidName] + ')'
-                        elif TokenSpaceGuidName:
-                            raise BadExpression('%s not found in DEC file' % TokenSpaceGuidName)
-
-                        ListItem, Size = ParseFieldValue(PcdValue)
-                    elif PcdValue.startswith('DEVICE_PATH') and PcdValue.endswith(')'):
-                        ListItem, Size = ParseFieldValue(PcdValue)
-                    else:
-                        ListItem = PcdValue.split(',')
-
-                    if type(ListItem) == type(0) or type(ListItem) == type(0L):
-                        for Index in range(0, Size):
-                            ValueStr += '0x%02X' % (int(ListItem) & 255)
-                            ListItem >>= 8
-                            ValueStr += ', '
-                            PcdValue = '{' + ValueStr[:-2] + '}'
-                    elif type(ListItem) == type(''):
-                        if ListItem.startswith('{') and ListItem.endswith('}'):
-                            PcdValue = ListItem
+                    for Item in PcdValue:
+                        if Item.startswith('UINT16'):
+                            ItemSize = 2
+                        elif Item.startswith('UINT32'):
+                            ItemSize = 4
+                        elif Item.startswith('UINT64'):
+                            ItemSize = 8
+                        else:
+                            ItemSize = 0
+                        Item = ValueExpressionEx(Item, self.PcdType, self._Symb)(True)
+
+                        if ItemSize == 0:
+                            ItemValue, ItemSize = ParseFieldValue(Item)
+                        else:
+                            ItemValue = ParseFieldValue(Item)[0]
+
+                        if type(ItemValue) == type(''):
+                            ItemValue = int(ItemValue, 16) if ItemValue.startswith('0x') else int(ItemValue)
+
+                        TmpValue = (ItemValue << (Size * 8)) | TmpValue
+                        Size = Size + ItemSize
+                else:
+                    TmpValue, Size = ParseFieldValue(PcdValue)
+                if type(TmpValue) == type(''):
+                    TmpValue = int(TmpValue)
+                else:
+                    PcdValue = '0x%0{}X'.format(Size) % (TmpValue)
+                if TmpValue < 0:
+                    raise  BadExpression('Type %s PCD Value is negative' % self.PcdType)
+                if self.PcdType == 'UINT8' and Size > 1:
+                    raise BadExpression('Type %s PCD Value Size is Larger than 1 byte' % self.PcdType)
+                if self.PcdType == 'UINT16' and Size > 2:
+                    raise BadExpression('Type %s PCD Value Size is Larger than 2 byte' % self.PcdType)
+                if self.PcdType == 'UINT32' and Size > 4:
+                    raise BadExpression('Type %s PCD Value Size is Larger than 4 byte' % self.PcdType)
+                if self.PcdType == 'UINT64' and Size > 8:
+                    raise BadExpression('Type %s PCD Value Size is Larger than 8 byte' % self.PcdType)
+            if self.PcdType in ['VOID*']:
+                try:
+                    TmpValue = long(PcdValue)
+                    TmpList = []
+                    if TmpValue.bit_length() == 0:
+                        PcdValue = '{0x00}'
                     else:
-                        LabelDict = {}
-                        ReLabel = re.compile('LABEL\((\w+)\)')
-                        ReOffset = re.compile('OFFSET_OF\((\w+)\)')
-                        for Index, Item in enumerate(ListItem):
-                            # for LABEL parse
-                            Item = Item.strip()
+                        for I in range((TmpValue.bit_length() + 7) / 8):
+                            TmpList.append('0x%02x' % ((TmpValue >> I * 8) & 0xff))
+                        PcdValue = '{' + ', '.join(TmpList) + '}'
+                except:
+                    if PcdValue.strip().startswith('{'):
+                        PcdValue = PcdValue.strip()[1:-1].strip()
+                        Size = 0
+                        ValueStr = ''
+                        TokenSpaceGuidName = ''
+                        if PcdValue.startswith('GUID') and PcdValue.endswith(')'):
                             try:
-                                LabelList = ReLabel.findall(Item)
-                                for Label in LabelList:
-                                    if Label not in LabelDict.keys():
-                                        LabelDict[Label] = str(Index)
-                                Item = ReLabel.sub('', Item)
+                                TokenSpaceGuidName = re.search('GUID\((\w+)\)', PcdValue).group(1)
                             except:
                                 pass
-                            try:
-                                OffsetList = ReOffset.findall(Item)
-                            except:
-                                pass
-                            for Offset in OffsetList:
-                                if Offset in LabelDict.keys():
-                                    Re = re.compile('OFFSET_OF\(%s\)'% Offset)
-                                    Item = Re.sub(LabelDict[Offset], Item)
-                                else:
-                                    raise BadExpression('%s not defined before use' % Offset)
-                            if Item.startswith('UINT16'):
-                                ItemSize = 2
-                            elif Item.startswith('UINT32'):
-                                ItemSize = 4
-                            elif Item.startswith('UINT64'):
-                                ItemSize = 8
-                            else:
-                                ItemSize = 0
-                            TmpValue = ValueExpressionEx(Item, self.PcdType, self._Symb)(True)
-                            Item = '0x%x' % TmpValue if type(TmpValue) != type('') else TmpValue
-                            if ItemSize == 0:
-                                ItemValue, ItemSize = ParseFieldValue(Item)
-                            else:
-                                ItemValue = ParseFieldValue(Item)[0]
-                            for I in range(0, ItemSize):
-                                ValueStr += '0x%02X' % (int(ItemValue) & 255)
-                                ItemValue >>= 8
+                            if TokenSpaceGuidName and TokenSpaceGuidName in self._Symb:
+                                PcdValue = 'GUID(' + self._Symb[TokenSpaceGuidName] + ')'
+                            elif TokenSpaceGuidName:
+                                raise BadExpression('%s not found in DEC file' % TokenSpaceGuidName)
+
+                            ListItem, Size = ParseFieldValue(PcdValue)
+                        elif PcdValue.startswith('DEVICE_PATH') and PcdValue.endswith(')'):
+                            ListItem, Size = ParseFieldValue(PcdValue)
+                        else:
+                            ListItem = PcdValue.split(',')
+
+                        if type(ListItem) == type(0) or type(ListItem) == type(0L):
+                            for Index in range(0, Size):
+                                ValueStr += '0x%02X' % (int(ListItem) & 255)
+                                ListItem >>= 8
                                 ValueStr += ', '
-                            Size += ItemSize
-
-                        if Size > 0:
-                            PcdValue = '{' + ValueStr[:-2] + '}'
+                                PcdValue = '{' + ValueStr[:-2] + '}'
+                        elif type(ListItem) == type(''):
+                            if ListItem.startswith('{') and ListItem.endswith('}'):
+                                PcdValue = ListItem
+                        else:
+                            LabelDict = {}
+                            ReLabel = re.compile('LABEL\((\w+)\)')
+                            ReOffset = re.compile('OFFSET_OF\((\w+)\)')
+                            for Index, Item in enumerate(ListItem):
+                                # for LABEL parse
+                                Item = Item.strip()
+                                try:
+                                    LabelList = ReLabel.findall(Item)
+                                    for Label in LabelList:
+                                        if Label not in LabelDict.keys():
+                                            LabelDict[Label] = str(Index)
+                                    Item = ReLabel.sub('', Item)
+                                except:
+                                    pass
+                                try:
+                                    OffsetList = ReOffset.findall(Item)
+                                except:
+                                    pass
+                                for Offset in OffsetList:
+                                    if Offset in LabelDict.keys():
+                                        Re = re.compile('OFFSET_OF\(%s\)'% Offset)
+                                        Item = Re.sub(LabelDict[Offset], Item)
+                                    else:
+                                        raise BadExpression('%s not defined before use' % Offset)
+                                ValueType = ""
+                                if Item.startswith('UINT16'):
+                                    ItemSize = 1
+                                    ValueType = "UINT8"
+                                elif Item.startswith('UINT16'):
+                                    ItemSize = 2
+                                    ValueType = "UINT16"
+                                elif Item.startswith('UINT32'):
+                                    ItemSize = 4
+                                elif Item.startswith('UINT64'):
+                                    ItemSize = 8
+                                else:
+                                    ItemSize = 0
+                                if ValueType:
+                                    TmpValue = ValueExpressionEx(Item, ValueType, self._Symb)(True)
+                                else:
+                                    TmpValue = ValueExpressionEx(Item, self.PcdType, self._Symb)(True)
+                                Item = '0x%x' % TmpValue if type(TmpValue) != type('') else TmpValue
+                                if ItemSize == 0:
+                                    ItemValue, ItemSize = ParseFieldValue(Item)
+                                else:
+                                    ItemValue = ParseFieldValue(Item)[0]
+                                for I in range(0, ItemSize):
+                                    ValueStr += '0x%02X' % (int(ItemValue) & 255)
+                                    ItemValue >>= 8
+                                    ValueStr += ', '
+                                Size += ItemSize
+
+                            if Size > 0:
+                                PcdValue = '{' + ValueStr[:-2] + '}'
+        if PcdValue == 'True':
+            PcdValue = '1'
+        if PcdValue == 'False':
+            PcdValue = '0'
         if RealValue:
             return PcdValue
 
 if __name__ == '__main__':
     pass
diff --git a/BaseTools/Source/Python/Workspace/DscBuildData.py b/BaseTools/Source/Python/Workspace/DscBuildData.py
index f30d3f7..25b2377 100644
--- a/BaseTools/Source/Python/Workspace/DscBuildData.py
+++ b/BaseTools/Source/Python/Workspace/DscBuildData.py
@@ -829,11 +829,17 @@ class DscBuildData(PlatformBuildClassObject):
             try:
                 ValueList[Index] = ValueExpression(ValueList[Index], GlobalData.gPlatformPcds)(True)
             except WrnExpression, Value:
                 ValueList[Index] = Value.result
             except BadExpression, Value:
-                EdkLogger.error('Parser', FORMAT_INVALID, Value, File=self.MetaFile, Line=self._LineIndex + 1)
+                DatumType = self._DecPcds[PcdCName, TokenSpaceGuid].DatumType
+                try:
+                    ValueList[Index] = ValueExpressionEx(ValueList[Index], DatumType, self._GuidDict)(True)
+                except BadExpression, Value:
+                    EdkLogger.error('Parser', FORMAT_INVALID, Value, File=self.MetaFile, Line=LineNo,
+                                    ExtraData="PCD [%s.%s] Value \"%s\" " % (
+                                    TokenSpaceGuid, PcdCName, ValueList[Index]))
             except EvaluationException, Excpt:
                 if hasattr(Excpt, 'Pcd'):
                     if Excpt.Pcd in GlobalData.gPlatformOtherPcds:
                         EdkLogger.error('Parser', FORMAT_INVALID, "Cannot use this PCD (%s) in an expression as"
                                         " it must be defined in a [PcdsFixedAtBuild] or [PcdsFeatureFlag] section"
@@ -843,17 +849,16 @@ class DscBuildData(PlatformBuildClassObject):
                         EdkLogger.error('Parser', FORMAT_INVALID, "PCD (%s) is not defined in DSC file" % Excpt.Pcd,
                                         File=self.MetaFile, Line=LineNo)
                 else:
                     EdkLogger.error('Parser', FORMAT_INVALID, "Invalid expression: %s" % str(Excpt),
                                     File=self.MetaFile, Line=LineNo)
+            if ValueList[Index] == 'True':
+                ValueList[Index] = '1'
+            if ValueList[Index] == 'False':
+                ValueList[Index] = '0'
+
         if ValueList[Index]:
-            DatumType = self._DecPcds[PcdCName, TokenSpaceGuid].DatumType
-            try:
-                ValueList[Index] = ValueExpressionEx(ValueList[Index], DatumType, self._GuidDict)(True)
-            except BadExpression, Value:
-                EdkLogger.error('Parser', FORMAT_INVALID, Value, File=self.MetaFile, Line=LineNo,
-                                ExtraData="PCD [%s.%s] Value \"%s\" " % (TokenSpaceGuid, PcdCName, ValueList[Index]))
             Valid, ErrStr = CheckPcdDatum(self._DecPcds[PcdCName, TokenSpaceGuid].DatumType, ValueList[Index])
             if not Valid:
                 EdkLogger.error('build', FORMAT_INVALID, ErrStr, File=self.MetaFile, Line=LineNo,
                                 ExtraData="%s.%s" % (TokenSpaceGuid, PcdCName))
             if PcdType in (MODEL_PCD_DYNAMIC_DEFAULT, MODEL_PCD_DYNAMIC_EX_DEFAULT):
diff --git a/BaseTools/Source/Python/Workspace/MetaFileParser.py b/BaseTools/Source/Python/Workspace/MetaFileParser.py
index 8f4b5e5..4ee129c 100644
--- a/BaseTools/Source/Python/Workspace/MetaFileParser.py
+++ b/BaseTools/Source/Python/Workspace/MetaFileParser.py
@@ -1988,18 +1988,10 @@ class DecParser(MetaFileParser):
                                 File=self.MetaFile, Line=self._LineIndex + 1)
 
             PcdValue = ValueList[0]
             if PcdValue:
                 try:
-                    ValueList[0] = ValueExpression(PcdValue, self._AllPcdDict)(True)
-                except WrnExpression, Value:
-                    ValueList[0] = Value.result
-                except BadExpression, Value:
-                    EdkLogger.error('Parser', FORMAT_INVALID, Value, File=self.MetaFile, Line=self._LineIndex + 1)
-
-            if ValueList[0]:
-                try:
                     ValueList[0] = ValueExpressionEx(ValueList[0], ValueList[1], self._GuidDict)(True)
                 except BadExpression, Value:
                     EdkLogger.error('Parser', FORMAT_INVALID, Value, ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
             # check format of default value against the datum type
             IsValid, Cause = CheckPcdDatum(ValueList[1], ValueList[0])
diff --git a/BaseTools/Source/Python/build/BuildReport.py b/BaseTools/Source/Python/build/BuildReport.py
index f2a6e6d..53d0039 100644
--- a/BaseTools/Source/Python/build/BuildReport.py
+++ b/BaseTools/Source/Python/build/BuildReport.py
@@ -35,19 +35,20 @@ from Common.Misc import GuidStructureByteArrayToGuidString
 from Common.Misc import GuidStructureStringToGuidString
 from Common.InfClassObject import gComponentType2ModuleType
 from Common.BuildToolError import FILE_WRITE_FAILURE
 from Common.BuildToolError import CODE_ERROR
 from Common.BuildToolError import COMMAND_FAILURE
+from Common.BuildToolError import FORMAT_INVALID
 from Common.LongFilePathSupport import OpenLongFilePath as open
 from Common.MultipleWorkspace import MultipleWorkspace as mws
 import Common.GlobalData as GlobalData
 from AutoGen.AutoGen import ModuleAutoGen
 from Common.Misc import PathClass
 from Common.String import NormPath
 from Common.DataType import *
 import collections
-from Common.Expression import ValueExpressionEx
+from Common.Expression import *
 
 ## Pattern to extract contents in EDK DXS files
 gDxsDependencyPattern = re.compile(r"DEPENDENCY_START(.+)DEPENDENCY_END", re.DOTALL)
 
 ## Pattern to find total FV total size, occupied size in flash report intermediate file
@@ -953,11 +954,15 @@ class PcdReport(object):
                     DecDefaultValue = self.DecPcdDefault.get((Pcd.TokenCName, Pcd.TokenSpaceGuidCName, DecType))
                     DscDefaultValue = self.DscPcdDefault.get((Pcd.TokenCName, Pcd.TokenSpaceGuidCName))
                     DscDefaultValBak = DscDefaultValue
                     DscDefaultValue = self.FdfPcdSet.get((Pcd.TokenCName, Key), DscDefaultValue)
                     if DscDefaultValue != DscDefaultValBak:
-                        DscDefaultValue = ValueExpressionEx(DscDefaultValue, Pcd.DatumType, self._GuidDict)(True)
+                        try:
+                            DscDefaultValue = ValueExpressionEx(DscDefaultValue, Pcd.DatumType, self._GuidDict)(True)
+                        except BadExpression, Value:
+                            EdkLogger.error('BuildReport', FORMAT_INVALID, "PCD Value: %s, Type: %s" %(DscDefaultValue, Pcd.DatumType))
+
                     InfDefaultValue = None
                     
                     PcdValue = DecDefaultValue
                     if DscDefaultValue:
                         PcdValue = DscDefaultValue
-- 
2.6.1.windows.1



^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [Patch] BaseTools: Enhance parse performance by optimize ValueExpressionEx
  2018-01-26 16:28 [Patch] BaseTools: Enhance parse performance by optimize ValueExpressionEx Yonghong Zhu
@ 2018-01-26 19:20 ` Andrew Fish
  2018-01-29  2:33   ` Zhu, Yonghong
  0 siblings, 1 reply; 3+ messages in thread
From: Andrew Fish @ 2018-01-26 19:20 UTC (permalink / raw)
  To: Yonghong Zhu; +Cc: edk2-devel, Yunhua Feng, Liming Gao

Any data on the performance improvement?

Thanks,

Andrew Fish

> On Jan 26, 2018, at 8:28 AM, Yonghong Zhu <yonghong.zhu@intel.com> wrote:
> 
> From: Yunhua Feng <yunhuax.feng@intel.com>
> 
> Optimize ValueExpressionEx function to enhance meta-data file parse
> performance.
> 
> Cc: Liming Gao <liming.gao@intel.com>
> Cc: Yonghong Zhu <yonghong.zhu@intel.com>
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Yunhua Feng <yunhuax.feng@intel.com>
> ---
> BaseTools/Source/Python/AutoGen/AutoGen.py         |  16 +-
> BaseTools/Source/Python/Common/Expression.py       | 286 +++++++++++----------
> BaseTools/Source/Python/Workspace/DscBuildData.py  |  19 +-
> .../Source/Python/Workspace/MetaFileParser.py      |   8 -
> BaseTools/Source/Python/build/BuildReport.py       |   9 +-
> 5 files changed, 167 insertions(+), 171 deletions(-)
> 
> diff --git a/BaseTools/Source/Python/AutoGen/AutoGen.py b/BaseTools/Source/Python/AutoGen/AutoGen.py
> index ab178c9..1cf50e8 100644
> --- a/BaseTools/Source/Python/AutoGen/AutoGen.py
> +++ b/BaseTools/Source/Python/AutoGen/AutoGen.py
> @@ -1243,10 +1243,11 @@ class PlatformAutoGen(AutoGen):
>         self.FvTargetList = self.Workspace.FvTargetList
>         self.AllPcdList = []
>         # get the original module/package/platform objects
>         self.BuildDatabase = Workspace.BuildDatabase
>         self.DscBuildDataObj = Workspace.Platform
> +        self._GuidDict = Workspace._GuidDict
> 
>         # flag indicating if the makefile/C-code file has been created or not
>         self.IsMakeFileCreated  = False
>         self.IsCodeFileCreated  = False
> 
> @@ -2461,26 +2462,13 @@ class PlatformAutoGen(AutoGen):
>             if FromPcd.DatumType not in [None, '']:
>                 ToPcd.DatumType = FromPcd.DatumType
>             if FromPcd.SkuInfoList not in [None, '', []]:
>                 ToPcd.SkuInfoList = FromPcd.SkuInfoList
>             # Add Flexible PCD format parse
> -            PcdValue = ToPcd.DefaultValue
> -            if PcdValue:
> -                try:
> -                    ToPcd.DefaultValue = ValueExpression(PcdValue)(True)
> -                except WrnExpression, Value:
> -                    ToPcd.DefaultValue = Value.result
> -                except BadExpression, Value:
> -                    EdkLogger.error('Parser', FORMAT_INVALID, 'PCD [%s.%s] Value "%s", %s' %(ToPcd.TokenSpaceGuidCName, ToPcd.TokenCName, ToPcd.DefaultValue, Value),
> -                                    File=self.MetaFile)
>             if ToPcd.DefaultValue:
> -                _GuidDict = {}
> -                for Pkg in self.PackageList:
> -                    Guids = Pkg.Guids
> -                    _GuidDict.update(Guids)
>                 try:
> -                    ToPcd.DefaultValue = ValueExpressionEx(ToPcd.DefaultValue, ToPcd.DatumType, _GuidDict)(True)
> +                    ToPcd.DefaultValue = ValueExpressionEx(ToPcd.DefaultValue, ToPcd.DatumType, self._GuidDict)(True)
>                 except BadExpression, Value:
>                     EdkLogger.error('Parser', FORMAT_INVALID, 'PCD [%s.%s] Value "%s", %s' %(ToPcd.TokenSpaceGuidCName, ToPcd.TokenCName, ToPcd.DefaultValue, Value),
>                                         File=self.MetaFile)
> 
>             # check the validation of datum
> diff --git a/BaseTools/Source/Python/Common/Expression.py b/BaseTools/Source/Python/Common/Expression.py
> index 55fa06d..d62fb48 100644
> --- a/BaseTools/Source/Python/Common/Expression.py
> +++ b/BaseTools/Source/Python/Common/Expression.py
> @@ -1,9 +1,9 @@
> ## @file
> # This file is used to parse and evaluate expression in directive or PCD value.
> #
> -# Copyright (c) 2011 - 2017, Intel Corporation. All rights reserved.<BR>
> +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>
> # This program and the accompanying materials
> # are licensed and made available under the terms and conditions of the BSD License
> # which accompanies this distribution.    The full text of the license may be found at
> # http://opensource.org/licenses/bsd-license.php
> #
> @@ -249,13 +249,10 @@ class ValueExpression(object):
>         self._NoProcess = False
>         if type(Expression) != type(''):
>             self._Expr = Expression
>             self._NoProcess = True
>             return
> -        if Expression.strip().startswith('{') and Expression.strip().endswith('}'):
> -            self._Expr = Expression
> -            self._NoProcess = True
> 
>         self._Expr = ReplaceExprMacro(Expression.strip(),
>                                   SymbolTable,
>                                   SupportedInMacroList)
> 
> @@ -291,17 +288,19 @@ class ValueExpression(object):
>         self._Expr = self._Expr.strip()
>         if RealValue and Depth == 0:
>             self._Token = self._Expr
>             if self.__IsNumberToken():
>                 return self._Expr
> -
> +            Token = ''
>             try:
>                 Token = self._GetToken()
> -                if type(Token) == type('') and Token.startswith('{') and Token.endswith('}') and self._Idx >= self._Len:
> -                    return self._Expr
>             except BadExpression:
>                 pass
> +            if type(Token) == type('') and Token.startswith('{') and Token.endswith('}') and self._Idx >= self._Len:
> +                if len(Token) != len(self._Expr.replace(' ', '')):
> +                    raise BadExpression
> +                return self._Expr
> 
>             self._Idx = 0
>             self._Token = ''
> 
>         Val = self._ConExpr()
> @@ -591,15 +590,14 @@ class ValueExpression(object):
>             self._LiteralToken.endswith('}'):
>             return True
> 
>         if self.HexPattern.match(self._LiteralToken):
>             Token = self._LiteralToken[2:]
> -            Token = Token.lstrip('0')
>             if not Token:
>                 self._LiteralToken = '0x0'
>             else:
> -                self._LiteralToken = '0x' + Token.lower()
> +                self._LiteralToken = '0x' + Token
>             return True
>         return False
> 
>     def _GetToken(self):
>         return self.__GetNList()
> @@ -734,147 +732,155 @@ class ValueExpressionEx(ValueExpression):
>         PcdValue = self.PcdValue
>         try:
>             PcdValue = ValueExpression.__call__(self, RealValue, Depth)
>         except WrnExpression, Value:
>             PcdValue = Value.result
> -
> -        if PcdValue == 'True':
> -            PcdValue = '1'
> -        if PcdValue == 'False':
> -            PcdValue = '0'
> -        if self.PcdType in ['UINT8', 'UINT16', 'UINT32', 'UINT64', 'BOOLEAN']:
> -            PcdValue = PcdValue.strip()
> -            if type(PcdValue) == type('') and PcdValue.startswith('{') and PcdValue.endswith('}'):
> -                PcdValue = PcdValue[1:-1].split(',')
> -            if type(PcdValue) == type([]):
> -                TmpValue = 0
> -                Size = 0
> -                for Item in PcdValue:
> -                    if Item.startswith('UINT16'):
> -                        ItemSize = 2
> -                    elif Item.startswith('UINT32'):
> -                        ItemSize = 4
> -                    elif Item.startswith('UINT64'):
> -                        ItemSize = 8
> -                    else:
> -                        ItemSize = 0
> -                    Item = ValueExpressionEx(Item, self.PcdType, self._Symb)(True)
> -
> -                    if ItemSize == 0:
> -                        ItemValue, ItemSize = ParseFieldValue(Item)
> -                    else:
> -                        ItemValue = ParseFieldValue(Item)[0]
> -
> -                    if type(ItemValue) == type(''):
> -                        ItemValue = int(ItemValue, 16) if ItemValue.startswith('0x') else int(ItemValue)
> -
> -                    TmpValue = (ItemValue << (Size * 8)) | TmpValue
> -                    Size = Size + ItemSize
> -            else:
> -                TmpValue, Size = ParseFieldValue(PcdValue)
> -            if type(TmpValue) == type(''):
> -                TmpValue = int(TmpValue)
> -            else:
> -                PcdValue = '0x%0{}X'.format(Size) % (TmpValue)
> -            if TmpValue < 0:
> -                raise  BadExpression('Type %s PCD Value is negative' % self.PcdType)
> -            if self.PcdType == 'UINT8' and Size > 1:
> -                raise BadExpression('Type %s PCD Value Size is Larger than 1 byte' % self.PcdType)
> -            if self.PcdType == 'UINT16' and Size > 2:
> -                raise BadExpression('Type %s PCD Value Size is Larger than 2 byte' % self.PcdType)
> -            if self.PcdType == 'UINT32' and Size > 4:
> -                raise BadExpression('Type %s PCD Value Size is Larger than 4 byte' % self.PcdType)
> -            if self.PcdType == 'UINT64' and Size > 8:
> -                raise BadExpression('Type %s PCD Value Size is Larger than 8 byte' % self.PcdType)
> -        if self.PcdType in ['VOID*']:
> -            try:
> -                TmpValue = long(PcdValue)
> -                TmpList = []
> -                if TmpValue.bit_length() == 0:
> -                    PcdValue = '{0x00}'
> -                else:
> -                    for I in range((TmpValue.bit_length() + 7) / 8):
> -                        TmpList.append('0x%02x' % ((TmpValue >> I * 8) & 0xff))
> -                    PcdValue = '{' + ', '.join(TmpList) + '}'
> -            except:
> -                if PcdValue.strip().startswith('{'):
> -                    PcdValue = PcdValue.strip()[1:-1].strip()
> +        except BadExpression:
> +            if self.PcdType in ['UINT8', 'UINT16', 'UINT32', 'UINT64', 'BOOLEAN']:
> +                PcdValue = PcdValue.strip()
> +                if type(PcdValue) == type('') and PcdValue.startswith('{') and PcdValue.endswith('}'):
> +                    PcdValue = PcdValue[1:-1].split(',')
> +                if type(PcdValue) == type([]):
> +                    TmpValue = 0
>                     Size = 0
> -                    ValueStr = ''
> -                    TokenSpaceGuidName = ''
> -                    if PcdValue.startswith('GUID') and PcdValue.endswith(')'):
> -                        try:
> -                            TokenSpaceGuidName = re.search('GUID\((\w+)\)', PcdValue).group(1)
> -                        except:
> -                            pass
> -                        if TokenSpaceGuidName and TokenSpaceGuidName in self._Symb:
> -                            PcdValue = 'GUID(' + self._Symb[TokenSpaceGuidName] + ')'
> -                        elif TokenSpaceGuidName:
> -                            raise BadExpression('%s not found in DEC file' % TokenSpaceGuidName)
> -
> -                        ListItem, Size = ParseFieldValue(PcdValue)
> -                    elif PcdValue.startswith('DEVICE_PATH') and PcdValue.endswith(')'):
> -                        ListItem, Size = ParseFieldValue(PcdValue)
> -                    else:
> -                        ListItem = PcdValue.split(',')
> -
> -                    if type(ListItem) == type(0) or type(ListItem) == type(0L):
> -                        for Index in range(0, Size):
> -                            ValueStr += '0x%02X' % (int(ListItem) & 255)
> -                            ListItem >>= 8
> -                            ValueStr += ', '
> -                            PcdValue = '{' + ValueStr[:-2] + '}'
> -                    elif type(ListItem) == type(''):
> -                        if ListItem.startswith('{') and ListItem.endswith('}'):
> -                            PcdValue = ListItem
> +                    for Item in PcdValue:
> +                        if Item.startswith('UINT16'):
> +                            ItemSize = 2
> +                        elif Item.startswith('UINT32'):
> +                            ItemSize = 4
> +                        elif Item.startswith('UINT64'):
> +                            ItemSize = 8
> +                        else:
> +                            ItemSize = 0
> +                        Item = ValueExpressionEx(Item, self.PcdType, self._Symb)(True)
> +
> +                        if ItemSize == 0:
> +                            ItemValue, ItemSize = ParseFieldValue(Item)
> +                        else:
> +                            ItemValue = ParseFieldValue(Item)[0]
> +
> +                        if type(ItemValue) == type(''):
> +                            ItemValue = int(ItemValue, 16) if ItemValue.startswith('0x') else int(ItemValue)
> +
> +                        TmpValue = (ItemValue << (Size * 8)) | TmpValue
> +                        Size = Size + ItemSize
> +                else:
> +                    TmpValue, Size = ParseFieldValue(PcdValue)
> +                if type(TmpValue) == type(''):
> +                    TmpValue = int(TmpValue)
> +                else:
> +                    PcdValue = '0x%0{}X'.format(Size) % (TmpValue)
> +                if TmpValue < 0:
> +                    raise  BadExpression('Type %s PCD Value is negative' % self.PcdType)
> +                if self.PcdType == 'UINT8' and Size > 1:
> +                    raise BadExpression('Type %s PCD Value Size is Larger than 1 byte' % self.PcdType)
> +                if self.PcdType == 'UINT16' and Size > 2:
> +                    raise BadExpression('Type %s PCD Value Size is Larger than 2 byte' % self.PcdType)
> +                if self.PcdType == 'UINT32' and Size > 4:
> +                    raise BadExpression('Type %s PCD Value Size is Larger than 4 byte' % self.PcdType)
> +                if self.PcdType == 'UINT64' and Size > 8:
> +                    raise BadExpression('Type %s PCD Value Size is Larger than 8 byte' % self.PcdType)
> +            if self.PcdType in ['VOID*']:
> +                try:
> +                    TmpValue = long(PcdValue)
> +                    TmpList = []
> +                    if TmpValue.bit_length() == 0:
> +                        PcdValue = '{0x00}'
>                     else:
> -                        LabelDict = {}
> -                        ReLabel = re.compile('LABEL\((\w+)\)')
> -                        ReOffset = re.compile('OFFSET_OF\((\w+)\)')
> -                        for Index, Item in enumerate(ListItem):
> -                            # for LABEL parse
> -                            Item = Item.strip()
> +                        for I in range((TmpValue.bit_length() + 7) / 8):
> +                            TmpList.append('0x%02x' % ((TmpValue >> I * 8) & 0xff))
> +                        PcdValue = '{' + ', '.join(TmpList) + '}'
> +                except:
> +                    if PcdValue.strip().startswith('{'):
> +                        PcdValue = PcdValue.strip()[1:-1].strip()
> +                        Size = 0
> +                        ValueStr = ''
> +                        TokenSpaceGuidName = ''
> +                        if PcdValue.startswith('GUID') and PcdValue.endswith(')'):
>                             try:
> -                                LabelList = ReLabel.findall(Item)
> -                                for Label in LabelList:
> -                                    if Label not in LabelDict.keys():
> -                                        LabelDict[Label] = str(Index)
> -                                Item = ReLabel.sub('', Item)
> +                                TokenSpaceGuidName = re.search('GUID\((\w+)\)', PcdValue).group(1)
>                             except:
>                                 pass
> -                            try:
> -                                OffsetList = ReOffset.findall(Item)
> -                            except:
> -                                pass
> -                            for Offset in OffsetList:
> -                                if Offset in LabelDict.keys():
> -                                    Re = re.compile('OFFSET_OF\(%s\)'% Offset)
> -                                    Item = Re.sub(LabelDict[Offset], Item)
> -                                else:
> -                                    raise BadExpression('%s not defined before use' % Offset)
> -                            if Item.startswith('UINT16'):
> -                                ItemSize = 2
> -                            elif Item.startswith('UINT32'):
> -                                ItemSize = 4
> -                            elif Item.startswith('UINT64'):
> -                                ItemSize = 8
> -                            else:
> -                                ItemSize = 0
> -                            TmpValue = ValueExpressionEx(Item, self.PcdType, self._Symb)(True)
> -                            Item = '0x%x' % TmpValue if type(TmpValue) != type('') else TmpValue
> -                            if ItemSize == 0:
> -                                ItemValue, ItemSize = ParseFieldValue(Item)
> -                            else:
> -                                ItemValue = ParseFieldValue(Item)[0]
> -                            for I in range(0, ItemSize):
> -                                ValueStr += '0x%02X' % (int(ItemValue) & 255)
> -                                ItemValue >>= 8
> +                            if TokenSpaceGuidName and TokenSpaceGuidName in self._Symb:
> +                                PcdValue = 'GUID(' + self._Symb[TokenSpaceGuidName] + ')'
> +                            elif TokenSpaceGuidName:
> +                                raise BadExpression('%s not found in DEC file' % TokenSpaceGuidName)
> +
> +                            ListItem, Size = ParseFieldValue(PcdValue)
> +                        elif PcdValue.startswith('DEVICE_PATH') and PcdValue.endswith(')'):
> +                            ListItem, Size = ParseFieldValue(PcdValue)
> +                        else:
> +                            ListItem = PcdValue.split(',')
> +
> +                        if type(ListItem) == type(0) or type(ListItem) == type(0L):
> +                            for Index in range(0, Size):
> +                                ValueStr += '0x%02X' % (int(ListItem) & 255)
> +                                ListItem >>= 8
>                                 ValueStr += ', '
> -                            Size += ItemSize
> -
> -                        if Size > 0:
> -                            PcdValue = '{' + ValueStr[:-2] + '}'
> +                                PcdValue = '{' + ValueStr[:-2] + '}'
> +                        elif type(ListItem) == type(''):
> +                            if ListItem.startswith('{') and ListItem.endswith('}'):
> +                                PcdValue = ListItem
> +                        else:
> +                            LabelDict = {}
> +                            ReLabel = re.compile('LABEL\((\w+)\)')
> +                            ReOffset = re.compile('OFFSET_OF\((\w+)\)')
> +                            for Index, Item in enumerate(ListItem):
> +                                # for LABEL parse
> +                                Item = Item.strip()
> +                                try:
> +                                    LabelList = ReLabel.findall(Item)
> +                                    for Label in LabelList:
> +                                        if Label not in LabelDict.keys():
> +                                            LabelDict[Label] = str(Index)
> +                                    Item = ReLabel.sub('', Item)
> +                                except:
> +                                    pass
> +                                try:
> +                                    OffsetList = ReOffset.findall(Item)
> +                                except:
> +                                    pass
> +                                for Offset in OffsetList:
> +                                    if Offset in LabelDict.keys():
> +                                        Re = re.compile('OFFSET_OF\(%s\)'% Offset)
> +                                        Item = Re.sub(LabelDict[Offset], Item)
> +                                    else:
> +                                        raise BadExpression('%s not defined before use' % Offset)
> +                                ValueType = ""
> +                                if Item.startswith('UINT16'):
> +                                    ItemSize = 1
> +                                    ValueType = "UINT8"
> +                                elif Item.startswith('UINT16'):
> +                                    ItemSize = 2
> +                                    ValueType = "UINT16"
> +                                elif Item.startswith('UINT32'):
> +                                    ItemSize = 4
> +                                elif Item.startswith('UINT64'):
> +                                    ItemSize = 8
> +                                else:
> +                                    ItemSize = 0
> +                                if ValueType:
> +                                    TmpValue = ValueExpressionEx(Item, ValueType, self._Symb)(True)
> +                                else:
> +                                    TmpValue = ValueExpressionEx(Item, self.PcdType, self._Symb)(True)
> +                                Item = '0x%x' % TmpValue if type(TmpValue) != type('') else TmpValue
> +                                if ItemSize == 0:
> +                                    ItemValue, ItemSize = ParseFieldValue(Item)
> +                                else:
> +                                    ItemValue = ParseFieldValue(Item)[0]
> +                                for I in range(0, ItemSize):
> +                                    ValueStr += '0x%02X' % (int(ItemValue) & 255)
> +                                    ItemValue >>= 8
> +                                    ValueStr += ', '
> +                                Size += ItemSize
> +
> +                            if Size > 0:
> +                                PcdValue = '{' + ValueStr[:-2] + '}'
> +        if PcdValue == 'True':
> +            PcdValue = '1'
> +        if PcdValue == 'False':
> +            PcdValue = '0'
>         if RealValue:
>             return PcdValue
> 
> if __name__ == '__main__':
>     pass
> diff --git a/BaseTools/Source/Python/Workspace/DscBuildData.py b/BaseTools/Source/Python/Workspace/DscBuildData.py
> index f30d3f7..25b2377 100644
> --- a/BaseTools/Source/Python/Workspace/DscBuildData.py
> +++ b/BaseTools/Source/Python/Workspace/DscBuildData.py
> @@ -829,11 +829,17 @@ class DscBuildData(PlatformBuildClassObject):
>             try:
>                 ValueList[Index] = ValueExpression(ValueList[Index], GlobalData.gPlatformPcds)(True)
>             except WrnExpression, Value:
>                 ValueList[Index] = Value.result
>             except BadExpression, Value:
> -                EdkLogger.error('Parser', FORMAT_INVALID, Value, File=self.MetaFile, Line=self._LineIndex + 1)
> +                DatumType = self._DecPcds[PcdCName, TokenSpaceGuid].DatumType
> +                try:
> +                    ValueList[Index] = ValueExpressionEx(ValueList[Index], DatumType, self._GuidDict)(True)
> +                except BadExpression, Value:
> +                    EdkLogger.error('Parser', FORMAT_INVALID, Value, File=self.MetaFile, Line=LineNo,
> +                                    ExtraData="PCD [%s.%s] Value \"%s\" " % (
> +                                    TokenSpaceGuid, PcdCName, ValueList[Index]))
>             except EvaluationException, Excpt:
>                 if hasattr(Excpt, 'Pcd'):
>                     if Excpt.Pcd in GlobalData.gPlatformOtherPcds:
>                         EdkLogger.error('Parser', FORMAT_INVALID, "Cannot use this PCD (%s) in an expression as"
>                                         " it must be defined in a [PcdsFixedAtBuild] or [PcdsFeatureFlag] section"
> @@ -843,17 +849,16 @@ class DscBuildData(PlatformBuildClassObject):
>                         EdkLogger.error('Parser', FORMAT_INVALID, "PCD (%s) is not defined in DSC file" % Excpt.Pcd,
>                                         File=self.MetaFile, Line=LineNo)
>                 else:
>                     EdkLogger.error('Parser', FORMAT_INVALID, "Invalid expression: %s" % str(Excpt),
>                                     File=self.MetaFile, Line=LineNo)
> +            if ValueList[Index] == 'True':
> +                ValueList[Index] = '1'
> +            if ValueList[Index] == 'False':
> +                ValueList[Index] = '0'
> +
>         if ValueList[Index]:
> -            DatumType = self._DecPcds[PcdCName, TokenSpaceGuid].DatumType
> -            try:
> -                ValueList[Index] = ValueExpressionEx(ValueList[Index], DatumType, self._GuidDict)(True)
> -            except BadExpression, Value:
> -                EdkLogger.error('Parser', FORMAT_INVALID, Value, File=self.MetaFile, Line=LineNo,
> -                                ExtraData="PCD [%s.%s] Value \"%s\" " % (TokenSpaceGuid, PcdCName, ValueList[Index]))
>             Valid, ErrStr = CheckPcdDatum(self._DecPcds[PcdCName, TokenSpaceGuid].DatumType, ValueList[Index])
>             if not Valid:
>                 EdkLogger.error('build', FORMAT_INVALID, ErrStr, File=self.MetaFile, Line=LineNo,
>                                 ExtraData="%s.%s" % (TokenSpaceGuid, PcdCName))
>             if PcdType in (MODEL_PCD_DYNAMIC_DEFAULT, MODEL_PCD_DYNAMIC_EX_DEFAULT):
> diff --git a/BaseTools/Source/Python/Workspace/MetaFileParser.py b/BaseTools/Source/Python/Workspace/MetaFileParser.py
> index 8f4b5e5..4ee129c 100644
> --- a/BaseTools/Source/Python/Workspace/MetaFileParser.py
> +++ b/BaseTools/Source/Python/Workspace/MetaFileParser.py
> @@ -1988,18 +1988,10 @@ class DecParser(MetaFileParser):
>                                 File=self.MetaFile, Line=self._LineIndex + 1)
> 
>             PcdValue = ValueList[0]
>             if PcdValue:
>                 try:
> -                    ValueList[0] = ValueExpression(PcdValue, self._AllPcdDict)(True)
> -                except WrnExpression, Value:
> -                    ValueList[0] = Value.result
> -                except BadExpression, Value:
> -                    EdkLogger.error('Parser', FORMAT_INVALID, Value, File=self.MetaFile, Line=self._LineIndex + 1)
> -
> -            if ValueList[0]:
> -                try:
>                     ValueList[0] = ValueExpressionEx(ValueList[0], ValueList[1], self._GuidDict)(True)
>                 except BadExpression, Value:
>                     EdkLogger.error('Parser', FORMAT_INVALID, Value, ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
>             # check format of default value against the datum type
>             IsValid, Cause = CheckPcdDatum(ValueList[1], ValueList[0])
> diff --git a/BaseTools/Source/Python/build/BuildReport.py b/BaseTools/Source/Python/build/BuildReport.py
> index f2a6e6d..53d0039 100644
> --- a/BaseTools/Source/Python/build/BuildReport.py
> +++ b/BaseTools/Source/Python/build/BuildReport.py
> @@ -35,19 +35,20 @@ from Common.Misc import GuidStructureByteArrayToGuidString
> from Common.Misc import GuidStructureStringToGuidString
> from Common.InfClassObject import gComponentType2ModuleType
> from Common.BuildToolError import FILE_WRITE_FAILURE
> from Common.BuildToolError import CODE_ERROR
> from Common.BuildToolError import COMMAND_FAILURE
> +from Common.BuildToolError import FORMAT_INVALID
> from Common.LongFilePathSupport import OpenLongFilePath as open
> from Common.MultipleWorkspace import MultipleWorkspace as mws
> import Common.GlobalData as GlobalData
> from AutoGen.AutoGen import ModuleAutoGen
> from Common.Misc import PathClass
> from Common.String import NormPath
> from Common.DataType import *
> import collections
> -from Common.Expression import ValueExpressionEx
> +from Common.Expression import *
> 
> ## Pattern to extract contents in EDK DXS files
> gDxsDependencyPattern = re.compile(r"DEPENDENCY_START(.+)DEPENDENCY_END", re.DOTALL)
> 
> ## Pattern to find total FV total size, occupied size in flash report intermediate file
> @@ -953,11 +954,15 @@ class PcdReport(object):
>                     DecDefaultValue = self.DecPcdDefault.get((Pcd.TokenCName, Pcd.TokenSpaceGuidCName, DecType))
>                     DscDefaultValue = self.DscPcdDefault.get((Pcd.TokenCName, Pcd.TokenSpaceGuidCName))
>                     DscDefaultValBak = DscDefaultValue
>                     DscDefaultValue = self.FdfPcdSet.get((Pcd.TokenCName, Key), DscDefaultValue)
>                     if DscDefaultValue != DscDefaultValBak:
> -                        DscDefaultValue = ValueExpressionEx(DscDefaultValue, Pcd.DatumType, self._GuidDict)(True)
> +                        try:
> +                            DscDefaultValue = ValueExpressionEx(DscDefaultValue, Pcd.DatumType, self._GuidDict)(True)
> +                        except BadExpression, Value:
> +                            EdkLogger.error('BuildReport', FORMAT_INVALID, "PCD Value: %s, Type: %s" %(DscDefaultValue, Pcd.DatumType))
> +
>                     InfDefaultValue = None
> 
>                     PcdValue = DecDefaultValue
>                     if DscDefaultValue:
>                         PcdValue = DscDefaultValue
> -- 
> 2.6.1.windows.1
> 
> _______________________________________________
> edk2-devel mailing list
> edk2-devel@lists.01.org
> https://lists.01.org/mailman/listinfo/edk2-devel



^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [Patch] BaseTools: Enhance parse performance by optimize ValueExpressionEx
  2018-01-26 19:20 ` Andrew Fish
@ 2018-01-29  2:33   ` Zhu, Yonghong
  0 siblings, 0 replies; 3+ messages in thread
From: Zhu, Yonghong @ 2018-01-29  2:33 UTC (permalink / raw)
  To: 'afish@apple.com'
  Cc: edk2-devel@lists.01.org, Feng, YunhuaX, Gao, Liming,
	Zhu, Yonghong

The bad performance was caused by newly PCD flexible value format support patch, eg: { 'AB', L'AB', 0x1, L"AB", UINT16(8)}
Original tool doesn't parse byte array PCD value format and let complier to do it, while after we add this new flexible value format support, BaseTool parse its format which cause 10s to 85s if the platform has > 6000 bytes of byte array Pcd, even it use original simplest format eg: {0x1, 0x1, 0x1}
So this patch do the enhancement from 85s to 15s if the byte array Pcd that use original simplest format, and reduce the impact if user doesn't use those new Pcd format.

Best Regards,
Zhu Yonghong

-----Original Message-----
From: afish@apple.com [mailto:afish@apple.com] 
Sent: Saturday, January 27, 2018 3:21 AM
To: Zhu, Yonghong <yonghong.zhu@intel.com>
Cc: edk2-devel@lists.01.org; Feng, YunhuaX <yunhuax.feng@intel.com>; Gao, Liming <liming.gao@intel.com>
Subject: Re: [edk2] [Patch] BaseTools: Enhance parse performance by optimize ValueExpressionEx

Any data on the performance improvement?

Thanks,

Andrew Fish

> On Jan 26, 2018, at 8:28 AM, Yonghong Zhu <yonghong.zhu@intel.com> wrote:
> 
> From: Yunhua Feng <yunhuax.feng@intel.com>
> 
> Optimize ValueExpressionEx function to enhance meta-data file parse 
> performance.
> 
> Cc: Liming Gao <liming.gao@intel.com>
> Cc: Yonghong Zhu <yonghong.zhu@intel.com>
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Yunhua Feng <yunhuax.feng@intel.com>
> ---
> BaseTools/Source/Python/AutoGen/AutoGen.py         |  16 +-
> BaseTools/Source/Python/Common/Expression.py       | 286 +++++++++++----------
> BaseTools/Source/Python/Workspace/DscBuildData.py  |  19 +-
> .../Source/Python/Workspace/MetaFileParser.py      |   8 -
> BaseTools/Source/Python/build/BuildReport.py       |   9 +-
> 5 files changed, 167 insertions(+), 171 deletions(-)
> 
> diff --git a/BaseTools/Source/Python/AutoGen/AutoGen.py 
> b/BaseTools/Source/Python/AutoGen/AutoGen.py
> index ab178c9..1cf50e8 100644
> --- a/BaseTools/Source/Python/AutoGen/AutoGen.py
> +++ b/BaseTools/Source/Python/AutoGen/AutoGen.py
> @@ -1243,10 +1243,11 @@ class PlatformAutoGen(AutoGen):
>         self.FvTargetList = self.Workspace.FvTargetList
>         self.AllPcdList = []
>         # get the original module/package/platform objects
>         self.BuildDatabase = Workspace.BuildDatabase
>         self.DscBuildDataObj = Workspace.Platform
> +        self._GuidDict = Workspace._GuidDict
> 
>         # flag indicating if the makefile/C-code file has been created or not
>         self.IsMakeFileCreated  = False
>         self.IsCodeFileCreated  = False
> 
> @@ -2461,26 +2462,13 @@ class PlatformAutoGen(AutoGen):
>             if FromPcd.DatumType not in [None, '']:
>                 ToPcd.DatumType = FromPcd.DatumType
>             if FromPcd.SkuInfoList not in [None, '', []]:
>                 ToPcd.SkuInfoList = FromPcd.SkuInfoList
>             # Add Flexible PCD format parse
> -            PcdValue = ToPcd.DefaultValue
> -            if PcdValue:
> -                try:
> -                    ToPcd.DefaultValue = ValueExpression(PcdValue)(True)
> -                except WrnExpression, Value:
> -                    ToPcd.DefaultValue = Value.result
> -                except BadExpression, Value:
> -                    EdkLogger.error('Parser', FORMAT_INVALID, 'PCD [%s.%s] Value "%s", %s' %(ToPcd.TokenSpaceGuidCName, ToPcd.TokenCName, ToPcd.DefaultValue, Value),
> -                                    File=self.MetaFile)
>             if ToPcd.DefaultValue:
> -                _GuidDict = {}
> -                for Pkg in self.PackageList:
> -                    Guids = Pkg.Guids
> -                    _GuidDict.update(Guids)
>                 try:
> -                    ToPcd.DefaultValue = ValueExpressionEx(ToPcd.DefaultValue, ToPcd.DatumType, _GuidDict)(True)
> +                    ToPcd.DefaultValue = 
> + ValueExpressionEx(ToPcd.DefaultValue, ToPcd.DatumType, 
> + self._GuidDict)(True)
>                 except BadExpression, Value:
>                     EdkLogger.error('Parser', FORMAT_INVALID, 'PCD [%s.%s] Value "%s", %s' %(ToPcd.TokenSpaceGuidCName, ToPcd.TokenCName, ToPcd.DefaultValue, Value),
>                                         File=self.MetaFile)
> 
>             # check the validation of datum diff --git 
> a/BaseTools/Source/Python/Common/Expression.py 
> b/BaseTools/Source/Python/Common/Expression.py
> index 55fa06d..d62fb48 100644
> --- a/BaseTools/Source/Python/Common/Expression.py
> +++ b/BaseTools/Source/Python/Common/Expression.py
> @@ -1,9 +1,9 @@
> ## @file
> # This file is used to parse and evaluate expression in directive or PCD value.
> #
> -# Copyright (c) 2011 - 2017, Intel Corporation. All rights 
> reserved.<BR>
> +# Copyright (c) 2011 - 2018, Intel Corporation. All rights 
> +reserved.<BR>
> # This program and the accompanying materials # are licensed and made 
> available under the terms and conditions of the BSD License
> # which accompanies this distribution.    The full text of the license may be found at
> # http://opensource.org/licenses/bsd-license.php
> #
> @@ -249,13 +249,10 @@ class ValueExpression(object):
>         self._NoProcess = False
>         if type(Expression) != type(''):
>             self._Expr = Expression
>             self._NoProcess = True
>             return
> -        if Expression.strip().startswith('{') and Expression.strip().endswith('}'):
> -            self._Expr = Expression
> -            self._NoProcess = True
> 
>         self._Expr = ReplaceExprMacro(Expression.strip(),
>                                   SymbolTable,
>                                   SupportedInMacroList)
> 
> @@ -291,17 +288,19 @@ class ValueExpression(object):
>         self._Expr = self._Expr.strip()
>         if RealValue and Depth == 0:
>             self._Token = self._Expr
>             if self.__IsNumberToken():
>                 return self._Expr
> -
> +            Token = ''
>             try:
>                 Token = self._GetToken()
> -                if type(Token) == type('') and Token.startswith('{') and Token.endswith('}') and self._Idx >= self._Len:
> -                    return self._Expr
>             except BadExpression:
>                 pass
> +            if type(Token) == type('') and Token.startswith('{') and Token.endswith('}') and self._Idx >= self._Len:
> +                if len(Token) != len(self._Expr.replace(' ', '')):
> +                    raise BadExpression
> +                return self._Expr
> 
>             self._Idx = 0
>             self._Token = ''
> 
>         Val = self._ConExpr()
> @@ -591,15 +590,14 @@ class ValueExpression(object):
>             self._LiteralToken.endswith('}'):
>             return True
> 
>         if self.HexPattern.match(self._LiteralToken):
>             Token = self._LiteralToken[2:]
> -            Token = Token.lstrip('0')
>             if not Token:
>                 self._LiteralToken = '0x0'
>             else:
> -                self._LiteralToken = '0x' + Token.lower()
> +                self._LiteralToken = '0x' + Token
>             return True
>         return False
> 
>     def _GetToken(self):
>         return self.__GetNList()
> @@ -734,147 +732,155 @@ class ValueExpressionEx(ValueExpression):
>         PcdValue = self.PcdValue
>         try:
>             PcdValue = ValueExpression.__call__(self, RealValue, Depth)
>         except WrnExpression, Value:
>             PcdValue = Value.result
> -
> -        if PcdValue == 'True':
> -            PcdValue = '1'
> -        if PcdValue == 'False':
> -            PcdValue = '0'
> -        if self.PcdType in ['UINT8', 'UINT16', 'UINT32', 'UINT64', 'BOOLEAN']:
> -            PcdValue = PcdValue.strip()
> -            if type(PcdValue) == type('') and PcdValue.startswith('{') and PcdValue.endswith('}'):
> -                PcdValue = PcdValue[1:-1].split(',')
> -            if type(PcdValue) == type([]):
> -                TmpValue = 0
> -                Size = 0
> -                for Item in PcdValue:
> -                    if Item.startswith('UINT16'):
> -                        ItemSize = 2
> -                    elif Item.startswith('UINT32'):
> -                        ItemSize = 4
> -                    elif Item.startswith('UINT64'):
> -                        ItemSize = 8
> -                    else:
> -                        ItemSize = 0
> -                    Item = ValueExpressionEx(Item, self.PcdType, self._Symb)(True)
> -
> -                    if ItemSize == 0:
> -                        ItemValue, ItemSize = ParseFieldValue(Item)
> -                    else:
> -                        ItemValue = ParseFieldValue(Item)[0]
> -
> -                    if type(ItemValue) == type(''):
> -                        ItemValue = int(ItemValue, 16) if ItemValue.startswith('0x') else int(ItemValue)
> -
> -                    TmpValue = (ItemValue << (Size * 8)) | TmpValue
> -                    Size = Size + ItemSize
> -            else:
> -                TmpValue, Size = ParseFieldValue(PcdValue)
> -            if type(TmpValue) == type(''):
> -                TmpValue = int(TmpValue)
> -            else:
> -                PcdValue = '0x%0{}X'.format(Size) % (TmpValue)
> -            if TmpValue < 0:
> -                raise  BadExpression('Type %s PCD Value is negative' % self.PcdType)
> -            if self.PcdType == 'UINT8' and Size > 1:
> -                raise BadExpression('Type %s PCD Value Size is Larger than 1 byte' % self.PcdType)
> -            if self.PcdType == 'UINT16' and Size > 2:
> -                raise BadExpression('Type %s PCD Value Size is Larger than 2 byte' % self.PcdType)
> -            if self.PcdType == 'UINT32' and Size > 4:
> -                raise BadExpression('Type %s PCD Value Size is Larger than 4 byte' % self.PcdType)
> -            if self.PcdType == 'UINT64' and Size > 8:
> -                raise BadExpression('Type %s PCD Value Size is Larger than 8 byte' % self.PcdType)
> -        if self.PcdType in ['VOID*']:
> -            try:
> -                TmpValue = long(PcdValue)
> -                TmpList = []
> -                if TmpValue.bit_length() == 0:
> -                    PcdValue = '{0x00}'
> -                else:
> -                    for I in range((TmpValue.bit_length() + 7) / 8):
> -                        TmpList.append('0x%02x' % ((TmpValue >> I * 8) & 0xff))
> -                    PcdValue = '{' + ', '.join(TmpList) + '}'
> -            except:
> -                if PcdValue.strip().startswith('{'):
> -                    PcdValue = PcdValue.strip()[1:-1].strip()
> +        except BadExpression:
> +            if self.PcdType in ['UINT8', 'UINT16', 'UINT32', 'UINT64', 'BOOLEAN']:
> +                PcdValue = PcdValue.strip()
> +                if type(PcdValue) == type('') and PcdValue.startswith('{') and PcdValue.endswith('}'):
> +                    PcdValue = PcdValue[1:-1].split(',')
> +                if type(PcdValue) == type([]):
> +                    TmpValue = 0
>                     Size = 0
> -                    ValueStr = ''
> -                    TokenSpaceGuidName = ''
> -                    if PcdValue.startswith('GUID') and PcdValue.endswith(')'):
> -                        try:
> -                            TokenSpaceGuidName = re.search('GUID\((\w+)\)', PcdValue).group(1)
> -                        except:
> -                            pass
> -                        if TokenSpaceGuidName and TokenSpaceGuidName in self._Symb:
> -                            PcdValue = 'GUID(' + self._Symb[TokenSpaceGuidName] + ')'
> -                        elif TokenSpaceGuidName:
> -                            raise BadExpression('%s not found in DEC file' % TokenSpaceGuidName)
> -
> -                        ListItem, Size = ParseFieldValue(PcdValue)
> -                    elif PcdValue.startswith('DEVICE_PATH') and PcdValue.endswith(')'):
> -                        ListItem, Size = ParseFieldValue(PcdValue)
> -                    else:
> -                        ListItem = PcdValue.split(',')
> -
> -                    if type(ListItem) == type(0) or type(ListItem) == type(0L):
> -                        for Index in range(0, Size):
> -                            ValueStr += '0x%02X' % (int(ListItem) & 255)
> -                            ListItem >>= 8
> -                            ValueStr += ', '
> -                            PcdValue = '{' + ValueStr[:-2] + '}'
> -                    elif type(ListItem) == type(''):
> -                        if ListItem.startswith('{') and ListItem.endswith('}'):
> -                            PcdValue = ListItem
> +                    for Item in PcdValue:
> +                        if Item.startswith('UINT16'):
> +                            ItemSize = 2
> +                        elif Item.startswith('UINT32'):
> +                            ItemSize = 4
> +                        elif Item.startswith('UINT64'):
> +                            ItemSize = 8
> +                        else:
> +                            ItemSize = 0
> +                        Item = ValueExpressionEx(Item, self.PcdType, 
> + self._Symb)(True)
> +
> +                        if ItemSize == 0:
> +                            ItemValue, ItemSize = ParseFieldValue(Item)
> +                        else:
> +                            ItemValue = ParseFieldValue(Item)[0]
> +
> +                        if type(ItemValue) == type(''):
> +                            ItemValue = int(ItemValue, 16) if 
> + ItemValue.startswith('0x') else int(ItemValue)
> +
> +                        TmpValue = (ItemValue << (Size * 8)) | TmpValue
> +                        Size = Size + ItemSize
> +                else:
> +                    TmpValue, Size = ParseFieldValue(PcdValue)
> +                if type(TmpValue) == type(''):
> +                    TmpValue = int(TmpValue)
> +                else:
> +                    PcdValue = '0x%0{}X'.format(Size) % (TmpValue)
> +                if TmpValue < 0:
> +                    raise  BadExpression('Type %s PCD Value is negative' % self.PcdType)
> +                if self.PcdType == 'UINT8' and Size > 1:
> +                    raise BadExpression('Type %s PCD Value Size is Larger than 1 byte' % self.PcdType)
> +                if self.PcdType == 'UINT16' and Size > 2:
> +                    raise BadExpression('Type %s PCD Value Size is Larger than 2 byte' % self.PcdType)
> +                if self.PcdType == 'UINT32' and Size > 4:
> +                    raise BadExpression('Type %s PCD Value Size is Larger than 4 byte' % self.PcdType)
> +                if self.PcdType == 'UINT64' and Size > 8:
> +                    raise BadExpression('Type %s PCD Value Size is Larger than 8 byte' % self.PcdType)
> +            if self.PcdType in ['VOID*']:
> +                try:
> +                    TmpValue = long(PcdValue)
> +                    TmpList = []
> +                    if TmpValue.bit_length() == 0:
> +                        PcdValue = '{0x00}'
>                     else:
> -                        LabelDict = {}
> -                        ReLabel = re.compile('LABEL\((\w+)\)')
> -                        ReOffset = re.compile('OFFSET_OF\((\w+)\)')
> -                        for Index, Item in enumerate(ListItem):
> -                            # for LABEL parse
> -                            Item = Item.strip()
> +                        for I in range((TmpValue.bit_length() + 7) / 8):
> +                            TmpList.append('0x%02x' % ((TmpValue >> I * 8) & 0xff))
> +                        PcdValue = '{' + ', '.join(TmpList) + '}'
> +                except:
> +                    if PcdValue.strip().startswith('{'):
> +                        PcdValue = PcdValue.strip()[1:-1].strip()
> +                        Size = 0
> +                        ValueStr = ''
> +                        TokenSpaceGuidName = ''
> +                        if PcdValue.startswith('GUID') and PcdValue.endswith(')'):
>                             try:
> -                                LabelList = ReLabel.findall(Item)
> -                                for Label in LabelList:
> -                                    if Label not in LabelDict.keys():
> -                                        LabelDict[Label] = str(Index)
> -                                Item = ReLabel.sub('', Item)
> +                                TokenSpaceGuidName = 
> + re.search('GUID\((\w+)\)', PcdValue).group(1)
>                             except:
>                                 pass
> -                            try:
> -                                OffsetList = ReOffset.findall(Item)
> -                            except:
> -                                pass
> -                            for Offset in OffsetList:
> -                                if Offset in LabelDict.keys():
> -                                    Re = re.compile('OFFSET_OF\(%s\)'% Offset)
> -                                    Item = Re.sub(LabelDict[Offset], Item)
> -                                else:
> -                                    raise BadExpression('%s not defined before use' % Offset)
> -                            if Item.startswith('UINT16'):
> -                                ItemSize = 2
> -                            elif Item.startswith('UINT32'):
> -                                ItemSize = 4
> -                            elif Item.startswith('UINT64'):
> -                                ItemSize = 8
> -                            else:
> -                                ItemSize = 0
> -                            TmpValue = ValueExpressionEx(Item, self.PcdType, self._Symb)(True)
> -                            Item = '0x%x' % TmpValue if type(TmpValue) != type('') else TmpValue
> -                            if ItemSize == 0:
> -                                ItemValue, ItemSize = ParseFieldValue(Item)
> -                            else:
> -                                ItemValue = ParseFieldValue(Item)[0]
> -                            for I in range(0, ItemSize):
> -                                ValueStr += '0x%02X' % (int(ItemValue) & 255)
> -                                ItemValue >>= 8
> +                            if TokenSpaceGuidName and TokenSpaceGuidName in self._Symb:
> +                                PcdValue = 'GUID(' + self._Symb[TokenSpaceGuidName] + ')'
> +                            elif TokenSpaceGuidName:
> +                                raise BadExpression('%s not found in 
> + DEC file' % TokenSpaceGuidName)
> +
> +                            ListItem, Size = ParseFieldValue(PcdValue)
> +                        elif PcdValue.startswith('DEVICE_PATH') and PcdValue.endswith(')'):
> +                            ListItem, Size = ParseFieldValue(PcdValue)
> +                        else:
> +                            ListItem = PcdValue.split(',')
> +
> +                        if type(ListItem) == type(0) or type(ListItem) == type(0L):
> +                            for Index in range(0, Size):
> +                                ValueStr += '0x%02X' % (int(ListItem) & 255)
> +                                ListItem >>= 8
>                                 ValueStr += ', '
> -                            Size += ItemSize
> -
> -                        if Size > 0:
> -                            PcdValue = '{' + ValueStr[:-2] + '}'
> +                                PcdValue = '{' + ValueStr[:-2] + '}'
> +                        elif type(ListItem) == type(''):
> +                            if ListItem.startswith('{') and ListItem.endswith('}'):
> +                                PcdValue = ListItem
> +                        else:
> +                            LabelDict = {}
> +                            ReLabel = re.compile('LABEL\((\w+)\)')
> +                            ReOffset = re.compile('OFFSET_OF\((\w+)\)')
> +                            for Index, Item in enumerate(ListItem):
> +                                # for LABEL parse
> +                                Item = Item.strip()
> +                                try:
> +                                    LabelList = ReLabel.findall(Item)
> +                                    for Label in LabelList:
> +                                        if Label not in LabelDict.keys():
> +                                            LabelDict[Label] = str(Index)
> +                                    Item = ReLabel.sub('', Item)
> +                                except:
> +                                    pass
> +                                try:
> +                                    OffsetList = ReOffset.findall(Item)
> +                                except:
> +                                    pass
> +                                for Offset in OffsetList:
> +                                    if Offset in LabelDict.keys():
> +                                        Re = re.compile('OFFSET_OF\(%s\)'% Offset)
> +                                        Item = Re.sub(LabelDict[Offset], Item)
> +                                    else:
> +                                        raise BadExpression('%s not defined before use' % Offset)
> +                                ValueType = ""
> +                                if Item.startswith('UINT16'):
> +                                    ItemSize = 1
> +                                    ValueType = "UINT8"
> +                                elif Item.startswith('UINT16'):
> +                                    ItemSize = 2
> +                                    ValueType = "UINT16"
> +                                elif Item.startswith('UINT32'):
> +                                    ItemSize = 4
> +                                elif Item.startswith('UINT64'):
> +                                    ItemSize = 8
> +                                else:
> +                                    ItemSize = 0
> +                                if ValueType:
> +                                    TmpValue = ValueExpressionEx(Item, ValueType, self._Symb)(True)
> +                                else:
> +                                    TmpValue = ValueExpressionEx(Item, self.PcdType, self._Symb)(True)
> +                                Item = '0x%x' % TmpValue if type(TmpValue) != type('') else TmpValue
> +                                if ItemSize == 0:
> +                                    ItemValue, ItemSize = ParseFieldValue(Item)
> +                                else:
> +                                    ItemValue = ParseFieldValue(Item)[0]
> +                                for I in range(0, ItemSize):
> +                                    ValueStr += '0x%02X' % (int(ItemValue) & 255)
> +                                    ItemValue >>= 8
> +                                    ValueStr += ', '
> +                                Size += ItemSize
> +
> +                            if Size > 0:
> +                                PcdValue = '{' + ValueStr[:-2] + '}'
> +        if PcdValue == 'True':
> +            PcdValue = '1'
> +        if PcdValue == 'False':
> +            PcdValue = '0'
>         if RealValue:
>             return PcdValue
> 
> if __name__ == '__main__':
>     pass
> diff --git a/BaseTools/Source/Python/Workspace/DscBuildData.py 
> b/BaseTools/Source/Python/Workspace/DscBuildData.py
> index f30d3f7..25b2377 100644
> --- a/BaseTools/Source/Python/Workspace/DscBuildData.py
> +++ b/BaseTools/Source/Python/Workspace/DscBuildData.py
> @@ -829,11 +829,17 @@ class DscBuildData(PlatformBuildClassObject):
>             try:
>                 ValueList[Index] = ValueExpression(ValueList[Index], GlobalData.gPlatformPcds)(True)
>             except WrnExpression, Value:
>                 ValueList[Index] = Value.result
>             except BadExpression, Value:
> -                EdkLogger.error('Parser', FORMAT_INVALID, Value, File=self.MetaFile, Line=self._LineIndex + 1)
> +                DatumType = self._DecPcds[PcdCName, TokenSpaceGuid].DatumType
> +                try:
> +                    ValueList[Index] = ValueExpressionEx(ValueList[Index], DatumType, self._GuidDict)(True)
> +                except BadExpression, Value:
> +                    EdkLogger.error('Parser', FORMAT_INVALID, Value, File=self.MetaFile, Line=LineNo,
> +                                    ExtraData="PCD [%s.%s] Value \"%s\" " % (
> +                                    TokenSpaceGuid, PcdCName, 
> + ValueList[Index]))
>             except EvaluationException, Excpt:
>                 if hasattr(Excpt, 'Pcd'):
>                     if Excpt.Pcd in GlobalData.gPlatformOtherPcds:
>                         EdkLogger.error('Parser', FORMAT_INVALID, "Cannot use this PCD (%s) in an expression as"
>                                         " it must be defined in a [PcdsFixedAtBuild] or [PcdsFeatureFlag] section"
> @@ -843,17 +849,16 @@ class DscBuildData(PlatformBuildClassObject):
>                         EdkLogger.error('Parser', FORMAT_INVALID, "PCD (%s) is not defined in DSC file" % Excpt.Pcd,
>                                         File=self.MetaFile, Line=LineNo)
>                 else:
>                     EdkLogger.error('Parser', FORMAT_INVALID, "Invalid expression: %s" % str(Excpt),
>                                     File=self.MetaFile, Line=LineNo)
> +            if ValueList[Index] == 'True':
> +                ValueList[Index] = '1'
> +            if ValueList[Index] == 'False':
> +                ValueList[Index] = '0'
> +
>         if ValueList[Index]:
> -            DatumType = self._DecPcds[PcdCName, TokenSpaceGuid].DatumType
> -            try:
> -                ValueList[Index] = ValueExpressionEx(ValueList[Index], DatumType, self._GuidDict)(True)
> -            except BadExpression, Value:
> -                EdkLogger.error('Parser', FORMAT_INVALID, Value, File=self.MetaFile, Line=LineNo,
> -                                ExtraData="PCD [%s.%s] Value \"%s\" " % (TokenSpaceGuid, PcdCName, ValueList[Index]))
>             Valid, ErrStr = CheckPcdDatum(self._DecPcds[PcdCName, TokenSpaceGuid].DatumType, ValueList[Index])
>             if not Valid:
>                 EdkLogger.error('build', FORMAT_INVALID, ErrStr, File=self.MetaFile, Line=LineNo,
>                                 ExtraData="%s.%s" % (TokenSpaceGuid, PcdCName))
>             if PcdType in (MODEL_PCD_DYNAMIC_DEFAULT, MODEL_PCD_DYNAMIC_EX_DEFAULT):
> diff --git a/BaseTools/Source/Python/Workspace/MetaFileParser.py 
> b/BaseTools/Source/Python/Workspace/MetaFileParser.py
> index 8f4b5e5..4ee129c 100644
> --- a/BaseTools/Source/Python/Workspace/MetaFileParser.py
> +++ b/BaseTools/Source/Python/Workspace/MetaFileParser.py
> @@ -1988,18 +1988,10 @@ class DecParser(MetaFileParser):
>                                 File=self.MetaFile, 
> Line=self._LineIndex + 1)
> 
>             PcdValue = ValueList[0]
>             if PcdValue:
>                 try:
> -                    ValueList[0] = ValueExpression(PcdValue, self._AllPcdDict)(True)
> -                except WrnExpression, Value:
> -                    ValueList[0] = Value.result
> -                except BadExpression, Value:
> -                    EdkLogger.error('Parser', FORMAT_INVALID, Value, File=self.MetaFile, Line=self._LineIndex + 1)
> -
> -            if ValueList[0]:
> -                try:
>                     ValueList[0] = ValueExpressionEx(ValueList[0], ValueList[1], self._GuidDict)(True)
>                 except BadExpression, Value:
>                     EdkLogger.error('Parser', FORMAT_INVALID, Value, ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
>             # check format of default value against the datum type
>             IsValid, Cause = CheckPcdDatum(ValueList[1], ValueList[0]) 
> diff --git a/BaseTools/Source/Python/build/BuildReport.py 
> b/BaseTools/Source/Python/build/BuildReport.py
> index f2a6e6d..53d0039 100644
> --- a/BaseTools/Source/Python/build/BuildReport.py
> +++ b/BaseTools/Source/Python/build/BuildReport.py
> @@ -35,19 +35,20 @@ from Common.Misc import 
> GuidStructureByteArrayToGuidString
> from Common.Misc import GuidStructureStringToGuidString from 
> Common.InfClassObject import gComponentType2ModuleType from 
> Common.BuildToolError import FILE_WRITE_FAILURE from 
> Common.BuildToolError import CODE_ERROR from Common.BuildToolError 
> import COMMAND_FAILURE
> +from Common.BuildToolError import FORMAT_INVALID
> from Common.LongFilePathSupport import OpenLongFilePath as open from 
> Common.MultipleWorkspace import MultipleWorkspace as mws import 
> Common.GlobalData as GlobalData from AutoGen.AutoGen import 
> ModuleAutoGen from Common.Misc import PathClass from Common.String 
> import NormPath from Common.DataType import * import collections -from 
> Common.Expression import ValueExpressionEx
> +from Common.Expression import *
> 
> ## Pattern to extract contents in EDK DXS files gDxsDependencyPattern 
> = re.compile(r"DEPENDENCY_START(.+)DEPENDENCY_END", re.DOTALL)
> 
> ## Pattern to find total FV total size, occupied size in flash report 
> intermediate file @@ -953,11 +954,15 @@ class PcdReport(object):
>                     DecDefaultValue = self.DecPcdDefault.get((Pcd.TokenCName, Pcd.TokenSpaceGuidCName, DecType))
>                     DscDefaultValue = self.DscPcdDefault.get((Pcd.TokenCName, Pcd.TokenSpaceGuidCName))
>                     DscDefaultValBak = DscDefaultValue
>                     DscDefaultValue = self.FdfPcdSet.get((Pcd.TokenCName, Key), DscDefaultValue)
>                     if DscDefaultValue != DscDefaultValBak:
> -                        DscDefaultValue = ValueExpressionEx(DscDefaultValue, Pcd.DatumType, self._GuidDict)(True)
> +                        try:
> +                            DscDefaultValue = ValueExpressionEx(DscDefaultValue, Pcd.DatumType, self._GuidDict)(True)
> +                        except BadExpression, Value:
> +                            EdkLogger.error('BuildReport', 
> + FORMAT_INVALID, "PCD Value: %s, Type: %s" %(DscDefaultValue, 
> + Pcd.DatumType))
> +
>                     InfDefaultValue = None
> 
>                     PcdValue = DecDefaultValue
>                     if DscDefaultValue:
>                         PcdValue = DscDefaultValue
> --
> 2.6.1.windows.1
> 
> _______________________________________________
> edk2-devel mailing list
> edk2-devel@lists.01.org
> https://lists.01.org/mailman/listinfo/edk2-devel



^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2018-01-29  2:27 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2018-01-26 16:28 [Patch] BaseTools: Enhance parse performance by optimize ValueExpressionEx Yonghong Zhu
2018-01-26 19:20 ` Andrew Fish
2018-01-29  2:33   ` Zhu, Yonghong

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox