Dr. Mabroka A. M.
CS802: Compliers
Spring 2017
symbol table management ادارة جدول الرموز لتخزين معلومات عن بنية البرنامجCompiler هو عبارة عن هيكلية بيانات يستخدمها املترجم
ً التي يتم استخدامها الحقا، يتم تجميع هذه املعلومات من قبل مراحل التحليل للمترجم.املصدر
.من قبل مراحل التركيب للحصول على الشفرة النهائية Symbol Tables Symbol tables are data structures that are used by compilers to hold information about source-program constructs. The information is collected incrementally by the analysis phases of a compiler and used by the synthesis phases to generate the target code. Entries in the symbol table contain information about an identifier such as its character string (or lexeme) , its type, its position in storage, and any other relevant information. Symbol tables typically need to support multiple declarations of the same identifier within a program. That is the scope of a declaration is the portion of a program to which the declaration applies. We shall implement scopes by setting up a separate symbol table for each scope. A program block with declarations will have its own symbol table with an entry for each declaration in the block. This approach also works for other constructs that set up scopes; for example, a class would have its own table, with an entry for each field and method.
ً ُ ) التي تمثل اسم املتغيرة تخزن فيlexeme( سلسلة الرموز،lexical analyzer خالل مرحلة املاسح:مثال Compiler و يتم اضافة معلومات عنها الى الجدول خالل املراحل القادمة من مراحل ال.جدول الرموز في،position ) و موقع تخزينها....، متغيرة، اسم روتين، و مهمتها (اسم مصفوفة،type مثل نوعها ُ تستخدم هذه املعلومات لتوليد الشفرة املناسبة لتخزين وcode generation مرحلة توليد الشفرة .عنونة هذه املتغيرة lexical العالقة بين جدول الرموز و . ذات الش ئlexemeالعمليتان الرئيسيتان اللتان تخصان جدول الرموز هما ادراج و استرجاع ال . املنسقة معهtoken يتم تخزين ال، في جدول الرموزlexemeعندما ُيخزن ال
36
Spring 2017
Dr. Mabroka A. M.
CS802: Compliers
العمليات التالية يتم تنفيذها على جدول الرموز: و هو اسم دالة (او اجراء) يقوم بادراج مدخلة في جدول الرموز ) insert ( s, t token
1.
lexeme
:sترجع التسلسل indexملدخلة جديدة لسلسلة s :tهي الtoken ) 2. lookup ( s
:sترجع التسلسل indexملدخلة sاذا كانت موجودة ،و اال ،ترجع .0 يستخدم ال lexical analyzerعملية loolupليحدد ما إذا كانت هذه ال lexemeقد تم تخزينها في جدول الرموز أم ال .إذا كانت غير موجودة ،يقوم ال lexicalباستدعاء العملية insertليدرج مدخلة جديدة في الجدول. العالقة بين جدول الرموز و syntax عندما تتم عملية ال insertمن قبل املاسح ،lexicalالبد من ترجيع مكان تسلسل هذه املدخلة index of entryفي جدول الرموز ،عندها ،يتم االتصال باللغوي syntaxإلبالغه بمكان تواجد هذه ً املدخلة في الجدول ،بناءا على ذلك ،يقوم اللغوي syntaxبتحديد مكان تواجد هذه املدخلة في ً التسلسل الهيكلي (الشجرة النحوية) و معرفة قيمة املدخلة (ترجيع قيمة ال tokenمن الجدول ،مثال idأو غيرها). معالجة الكلمات املحجوزة يمكن للعمليتين السابقتين :االدراج insertو البحث lookupان تعالج أي مجموعة من الكلمات ً املحجوزة .مثال :جملة ifالشرطية يتم التعامل معها من قبل ال lexicalو ادراجها في جدول الرموز عن طريق العمليةinsert ( “if”, if) : Lexeme token أي عملية lookupترجع ifكـ ،tokenلذلك ،اليمكن استخدامها كمتغيرة .id
37
Spring 2017
CS802: Compliers
Dr. Mabroka A. M.
تنفيذ جدول الرموز implementation of symbol table ً البد أوال من تحديد نوع هيكلية البيانات املراد استخدامها كجدول رموز ،و كذلك تحديد نوع الهيكلية للبيانات املدخلة .أحد انواع هذه الهيكليات هي كالتالي:
Class Env implements chained symboi tables
38
Spring 2017
CS802: Compliers
Dr. Mabroka A. M.
معالج الخطأ error handler يعتبر معالج الخطأ من املراحل التي يتم االتصال بها من قبل جميع مراحل ال Compilerاالخرى ،و ذلك ملعرفة الخطأ و مكان تواجده في البرنامج املصدر .اكتشاف الخطا من املهام الجديرة باالهتمام من ً قبل مصممي ال Compilerحيث يساعد املبرمج على معرفة و تحديد مكان الخطأ و أحيانا تزويده بالتصحيح املحتمل لهذا الخطأ. أنواع الخطأ :يمكن ان يحتوي البرنامج املصدر على أخطاء عند مختلف مراحل ترجمته. :Lexical error .1مثل نسيان اسم متغيرة او الخطأ في حروفها كأن تبدأ برقم بدل حرف او الخطأ في كتابة الكلمات املحجوزة او العالمات. ;x y مثال: Missing comma 1a = b Misspelling identifier Syntactic error .2 مثل عدم اتزان االقواس في تعبير حسابي a = (a+(b/c)-d Semantic error .3 عدم توافق النوعية ،مثل وضع متغيرة من نوع ما في متغيرة اخرى من نوع مختلف ;char a …... ..... ;b = b + a Logical error .4 مثل التكرار االنهائي
39
Spring 2017
CS802: Compliers
Dr. Mabroka A. M.
العالقة بين معالج الخطأ و syntax بعض االخطاء يمكن اكتشافها اثناء مرحلة التحليل الخطي ،lexical analysisلكن معظمها يتم اكتشافه و معالجته اثناء مرحلة التحليل للغوي .syntax analysisأحد االسباب تمك في ان معظم االخطاء التي يقع فيها املبرمجين اخطاء لغوية مخالفة لقواعد اللغة .الى جانب ذلك ،يمكن ان يتم تمرير سلسلة من ال tokenمن قبل ال lexicalو يستقبلها اللغوي syntaxالذي يكتشف انها قد ُمررت بطريقة خاطئة.سبب آخر يعزو الى طريقة االعراب parsing methodالتي يتبعها اللغوي لبناء هيكلية تسلسلية يتم فيها اكتشاف الخطأ بفعالية. .1 .2 .3
مهام معالج الخطأ اصدار تقارير بوجود أخطا بطريقة واضحة مثل نوع و مكان الخطا بدقة. ً تغطية حدث هذا الخطأ ليكون قادرا على اكتشاف االخطاء الالحقة. ان ال يتسبب في بطئ معالجة البرنامج الصحيح.
اكتشاف الخطأ و معالجته يقوم معالج االخطاء لدى اكتشافه أي خطأ سواء من قبل املاسح lexicalأو اللغوي syntax باصدار تقرير عن الخطأ و رقم السطر املوجود فيه الخطأ. ً و ال يوجد طريقة ثابتة ملعالجة الخطأ ،فقد يدفع اللغوي أحيانا البرنامج الى التوقف لدى ً اكتشاف الخطا تجنبا لوجود أخطاء أخرى مترتبة على الخطأ السابق .و قد تستمر ترجمة البرنامج بعد تخزين معلومات عن ذلك الخطا و اصدار تقارير عنه فيما بعد.
40
Spring 2017
CS802: Compliers
Dr. Mabroka A. M.
مرحلة التحليل الداللي (املنطقي) semantic analysis يعتبر املحلل الداللي احد أهم مراحل ال Compilerالتي يتم فيها فحص نوعية املتغيرات و التأكد من توافقها مع العمليات املقام عليها .و تتم عملية الفحص على الشجرة النحوية التي ينتجها الsyntax لتكون هي نفسها املخرج من مرحلة التحليل الداللي و لكن قد تم فحصها و اصدار تقارير عليها. الفحص الذي ُيجريه ال Compilerعلى البرنامج املصدر ُيسمى بالفحص االستاتيكي ،بينما الفحص
الذي ُيجرى عند تنفيذ البرنامج الهدف ُيسمى بالفحص الديناميكي. ً بصفة اساسية ،أي فحص يمكن أن ُيجرى ديناميكيا ،إذا تم التعامل مع قيمة املتغيرة مرفقة بنوعيتها uniqueness checksأو flow of control checksفحص تدفق التحكم. هناك أمثلة متعددة للفحص االستاتيكي ،أحدها هو فحص النوعية.
The design space of types فحص النوعية type checking إذا لم يكن هناك توافق بين املعامالت و العمليات املقامة عليها ،فعلى ال Compilerان يصدر تقرير بوجود خطأ .إذا كانت هناك عالمة operatorغير متوافقة مع معامالتها مثل: ; ] char a[ size ….. ; int x = a [ I ] + 1 ……. نالحظ ان املتغير xمن نوع ،intبينما ] a [ Iمن نوع charو كالهما غير متوافقان في النوعية. 41
CS802: Compliers
Spring 2017
Dr. Mabroka A. M.
الفاحص type checker
ُ هو عبارة عن برنامج يتحقق من ان نوعية البناء تطابق تماما املقام املوجود فيه .بمعنى آخر، تطابق املعامالت و نوعيتها مع العملية املقامة عليها مثل عملية باقي القسمة التي ال تقبل إال
متغيرات من نوع صحيح .integer intermediate representation
Intermediate code generator
parse tree
Type checker
parse tree
parser
Tokens
Position of type checker تصميم فاحص النوعية يعتمد تصميم فاحص النوعية للغة ما على كل من: معلومات عن القواعد النحوية لإلنشاءات constructsالتي تتكون منها هذه اللغة. الفكرة العامة للنوعيات notation of types مجموعلة القوانين التي تنسب االنواع typesالى إنشاءات اللغة .language constructsبصفة عامة ،االنواع إما أن تكون اساسية او مركبة .االساسية و هي التي ال تحتوي على هيكلية داخلية مثل ،integer, char, float, Boolean :و املركبة و هي التي تتكون من انواع اساسية متعددة مثل املصفوفات ،و الهيكليات املركبة االخرى. العالقة بين semanticو error handler يمكن ان يكتشف ال semanticخطأ او مجموعة من االخطاء في البرنامج املصدر ،لذا ،على ً فاحص النوعية مثال ان يتعامل مع االخطاء بطريقة منطقية في حالة و جودها ،وإال ،فإن معالج ُ الخطأ يفقد بعض املعلومات املترتبة على النوع و التي من شأنها أن تؤثر في سير البرنامج .فعندما يكتشف فاحص النوعية خطأ ماُ ،يعلم معالج الخطأ بذلك و يستمر في فحص باقي البرنامج و ال يتأثر باالخطاء التي يكتشفها هو او يكتشفها معالج الخطأ.
42
Spring 2017
Dr. Mabroka A. M.
CS802: Compliers
مولد الشفرة الوسطية intermediate code generator
ً بما أن مرحلة توليد الشفرة الوسطية تعتمد هي االخرى أيضا على البرنامج املصدر front end ً ،phaseإذن ،باستخدام تمثيل وسط معرف جيدا ،يمكن بناء مترجم Compilerللغة iالى لغة
االلة jعن طريق دمج front end for language iمع .back end for machine j
Code optimizer & code generator
back end
intermediate code representation
Intermediate code generator
parse tree Type checker
parse tree
parser
Tokens
front end | logical structure of a compiler front end
يمكن ل Compilerأن ُيشيد كتمثيل وسطي متتالي لترجمة البرنامج املصدر الى البرنامج الهدف.
A compiler might use a sequence of intermediate representations
-
لغات وسطية intermediate languages تصميم التمثيل الوسطي يختلف من Compilerالى آخر و يرمز له بالرمز .IR ُ يمكن ان يكون التمثيل الوسطي أحد لغات البرمجة مثل لغة Cحيث تستخدم كتمثيل وسطي و يمكن ترجمتها الى شفرة آلة مناسبة. مترجم لغة C++االصلي (النسخة االصلية ملترجم )C++ C++ Compiler يتكون من front endيولد شفرة وسطية و هي برنامج .Cثم يأتي دور C Compilerالذي يمثل .backend 43
Dr. Mabroka A. M.
CS802: Compliers
Spring 2017
:مثال Consider the statement do i = i+1; while ( a [ i ] < v) ; three adress statements عنوان مرمز الول جملة فقط
وحدات من الفراغ8 مصفوفة عناصر كل عنصر فيها يأخذ
.java bytecodes لsoftware interpreter هيJVM java compiler هي لغة تمثيل شفرة وسطية ينتجهاJava bytecodes .multiple platforms يزودنا بالتوافقية عبرJVM interpreter خالل زمن الثنفيذ الى مجموعة تعليمات لاللةbytecodes يترجم الJIT Java Compiler .native hardware الهدف
44
Dr. Mabroka A. M.
CS802: Compliers
Spring 2017
code optimizer مقلص الشفرة كونها تعتمد على البرنامجfront end هيcode generator و مرحلةcode optimizer تعتبر مرحلة .الهدف
Position of code optimization
Optimisations Optimisations can be done by a compiler in three places: In the source code (i.e., on the abstract syntax), in the intermediate code, and in the machine code. Some optimisations can be specific to the source language or the machine language, but it makes sense to perform optimisations mainly in the intermediate language, as the optimisations hence can be shared among all compilers that use the same intermediate language. Also, the intermediate language is typically simpler than both the source language and the machine language, making the effort of doing optimisations smaller. Optimising compilers have a wide array of optimisations that they can employ, but we will mention only a few and just hint at how they can be implemented.
Common subexpression elimination. In the statement a[i] := a[i]+2, the address for a[i] is calculated twice. This double calculation can be eliminated by storing the address in a temporary variable when the address is first calculated, and then use this variable instead of calculating the address again. Simple methods for common subexpression elimination work on basic blocks, i.e., straight-line code without jumps or labels, but more advanced methods can eliminate duplicated calculations even across jumps.
Code hoisting. If part of the computation inside a loop is independent of the variables that change inside the loop, it can be moved outside the loop and only calculated once. For example, in the loop
while (j < k) { sum = sum + a[ i ] [ j ] ; j++ ; } 45
Dr. Mabroka A. M.
CS802: Compliers
Spring 2017
a large part of the address calculation for a[i][j] can be done without knowing j. This part can be moved outside the loop so it will only be calculated once. Note that this optimisation ca not be done on source-code level, as the address calculations are not visible there. For the same reason, the optimised version is not shown here. If k may be less than or equal to j, the loop body may never be entered and we may, hence, unnecessarily execute the code that was moved out of the loop. This might even generate a run-time error. Hence, we can unroll the loop once to if (j < k) { sum = sum + a[i][j]; j++; while (j < k) { sum = sum + a[i][j]; j++; } } The loop-independent part(s) may now without risk be calculated in the unrolled part and reused in the non-unrolled part. Again, this optimisation is not shown. ď&#x201A;ˇ
Constant propagation. A variable may, at some points in the program, have a value that is always equal to a known constant. When such a variable is used in a calculation, this calculation can often be simplified after replacing the variable by the constant that is guaranteed to be its value. Furthermore, the variable that holds the results of this computation may now also become constant, which may enable even more compile-time reduction. Constant-propagation algorithms first trace the flow of constant values through the program, and then reduce calculations. More advanced methods also look at conditions, so they can exploit that after a test on, e.g., x = 0, x is, indeed, the constant 0.
ď&#x201A;ˇ
Index-check elimination. some compilers insert runtime checks to catch cases when an index is outside the bounds of the array. Some of these checks can be removed by the compiler. One way of doing this is to see if the tests on the index are subsumed by earlier tests or ensured by assignments. For example, assume that, in the loop shown above, a is declared to be a k_k array. This means that the entry test for the loop will ensure that j is always less than the upper bound on the array, so this part of the index test can be eliminated. If j is initialised to 0 before entering the loop, we can use this to conclude that we do not need to check the lower bound either.
46
Spring 2017
CS802: Compliers
Dr. Mabroka A. M.
مولد الشفرة code generator ُ تعد هذه املرحلة هي االخيرة من مراحل ال ،Compilerحيث تأخذ هذه املرحلة التمثيل ُ الوسطي للبرنامج املصدر كمدخالت ثم تولد شفرة مطابقة للبرنامج املصدر.
Position of code generation .1 .2 .3
مهام code generation اختيار التعليمة (يختار التعليمات املناسبة لاللة الهدف املقابلة للشفرة الوسط). التعامل مع السجالت (العنونة و التخزين). طلب التعليمة (حيث يقرر code generationفي أي ترتيب يجدول تنفيذ التعليمات).
تصميم code generation ً يتم تصميم code generationوفقا للمهام السابقة التي يؤديها. يستخدم code generationاملعلومات املوجودة في جدول الرموز ليحدد run-time addressesل data objectsالتي تدل عليها االسماء في .IR يعتمد code generatorفي توليد ال codeعلى نوع .target-machine architecture هناك نوعان رئيسيان ل target-machine architectureهما:RISC Reduced Instruction Set Computer CISC Complex Instruction Set Computer Stack based
47