| OLD | NEW | 
|---|
| 1 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file | 
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a | 
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. | 
| 4 | 4 | 
| 5 #ifndef VM_INTERMEDIATE_LANGUAGE_H_ | 5 #ifndef VM_INTERMEDIATE_LANGUAGE_H_ | 
| 6 #define VM_INTERMEDIATE_LANGUAGE_H_ | 6 #define VM_INTERMEDIATE_LANGUAGE_H_ | 
| 7 | 7 | 
| 8 #include "vm/allocation.h" | 8 #include "vm/allocation.h" | 
| 9 #include "vm/ast.h" | 9 #include "vm/ast.h" | 
| 10 #include "vm/growable_array.h" | 10 #include "vm/growable_array.h" | 
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 139 | 139 | 
| 140   virtual intptr_t InputCount() const = 0; | 140   virtual intptr_t InputCount() const = 0; | 
| 141   virtual Value* InputAt(intptr_t i) const = 0; | 141   virtual Value* InputAt(intptr_t i) const = 0; | 
| 142   virtual void SetInputAt(intptr_t i, Value* value) = 0; | 142   virtual void SetInputAt(intptr_t i, Value* value) = 0; | 
| 143 | 143 | 
| 144   // Static type of the computation. | 144   // Static type of the computation. | 
| 145   virtual RawAbstractType* StaticType() const = 0; | 145   virtual RawAbstractType* StaticType() const = 0; | 
| 146 | 146 | 
| 147   // Mutate assigned_vars to add the local variable index for all | 147   // Mutate assigned_vars to add the local variable index for all | 
| 148   // frame-allocated locals assigned to by the computation. | 148   // frame-allocated locals assigned to by the computation. | 
| 149   virtual void RecordAssignedVars(BitVector* assigned_vars); | 149   virtual void RecordAssignedVars(BitVector* assigned_vars, | 
|  | 150                                   intptr_t fixed_parameter_count); | 
| 150 | 151 | 
| 151   virtual const char* DebugName() const = 0; | 152   virtual const char* DebugName() const = 0; | 
| 152 | 153 | 
| 153   // Printing support. These functions are sometimes overridden for custom | 154   // Printing support. These functions are sometimes overridden for custom | 
| 154   // formatting. Otherwise, it prints in the format "opcode(op1, op2, op3)". | 155   // formatting. Otherwise, it prints in the format "opcode(op1, op2, op3)". | 
| 155   virtual void PrintTo(BufferFormatter* f) const; | 156   virtual void PrintTo(BufferFormatter* f) const; | 
| 156   virtual void PrintOperandsTo(BufferFormatter* f) const; | 157   virtual void PrintOperandsTo(BufferFormatter* f) const; | 
| 157 | 158 | 
| 158   // Returns structure describing location constraints required | 159   // Returns structure describing location constraints required | 
| 159   // to emit native code for this computation. | 160   // to emit native code for this computation. | 
| (...skipping 605 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 765         context_level_(context_level) { | 766         context_level_(context_level) { | 
| 766     inputs_[0] = value; | 767     inputs_[0] = value; | 
| 767   } | 768   } | 
| 768 | 769 | 
| 769   DECLARE_COMPUTATION(StoreLocal) | 770   DECLARE_COMPUTATION(StoreLocal) | 
| 770 | 771 | 
| 771   const LocalVariable& local() const { return local_; } | 772   const LocalVariable& local() const { return local_; } | 
| 772   Value* value() const { return inputs_[0]; } | 773   Value* value() const { return inputs_[0]; } | 
| 773   intptr_t context_level() const { return context_level_; } | 774   intptr_t context_level() const { return context_level_; } | 
| 774 | 775 | 
| 775   virtual void RecordAssignedVars(BitVector* assigned_vars); | 776   virtual void RecordAssignedVars(BitVector* assigned_vars, | 
|  | 777                                   intptr_t fixed_parameter_count); | 
| 776 | 778 | 
| 777   virtual void PrintOperandsTo(BufferFormatter* f) const; | 779   virtual void PrintOperandsTo(BufferFormatter* f) const; | 
| 778 | 780 | 
| 779  private: | 781  private: | 
| 780   const LocalVariable& local_; | 782   const LocalVariable& local_; | 
| 781   const intptr_t context_level_; | 783   const intptr_t context_level_; | 
| 782 | 784 | 
| 783   DISALLOW_COPY_AND_ASSIGN(StoreLocalComp); | 785   DISALLOW_COPY_AND_ASSIGN(StoreLocalComp); | 
| 784 }; | 786 }; | 
| 785 | 787 | 
| (...skipping 1001 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1787   // assigned frame-allocated local variables in the block.  As a side | 1789   // assigned frame-allocated local variables in the block.  As a side | 
| 1788   // effect of this function, the set of basic block predecessors (e.g., | 1790   // effect of this function, the set of basic block predecessors (e.g., | 
| 1789   // block entry instructions of predecessor blocks) and also the last | 1791   // block entry instructions of predecessor blocks) and also the last | 
| 1790   // instruction in the block is recorded in each entry instruction. | 1792   // instruction in the block is recorded in each entry instruction. | 
| 1791   virtual void DiscoverBlocks( | 1793   virtual void DiscoverBlocks( | 
| 1792       BlockEntryInstr* current_block, | 1794       BlockEntryInstr* current_block, | 
| 1793       GrowableArray<BlockEntryInstr*>* preorder, | 1795       GrowableArray<BlockEntryInstr*>* preorder, | 
| 1794       GrowableArray<BlockEntryInstr*>* postorder, | 1796       GrowableArray<BlockEntryInstr*>* postorder, | 
| 1795       GrowableArray<intptr_t>* parent, | 1797       GrowableArray<intptr_t>* parent, | 
| 1796       GrowableArray<BitVector*>* assigned_vars, | 1798       GrowableArray<BitVector*>* assigned_vars, | 
| 1797       intptr_t variable_count) { | 1799       intptr_t variable_count, | 
|  | 1800       intptr_t fixed_parameter_count) { | 
| 1798     // Never called for instructions except block entries and branches. | 1801     // Never called for instructions except block entries and branches. | 
| 1799     UNREACHABLE(); | 1802     UNREACHABLE(); | 
| 1800   } | 1803   } | 
| 1801 | 1804 | 
| 1802   // Mutate assigned_vars to add the local variable index for all | 1805   // Mutate assigned_vars to add the local variable index for all | 
| 1803   // frame-allocated locals assigned to by the instruction. | 1806   // frame-allocated locals assigned to by the instruction. | 
| 1804   virtual void RecordAssignedVars(BitVector* assigned_vars); | 1807   virtual void RecordAssignedVars(BitVector* assigned_vars, | 
|  | 1808                                   intptr_t fixed_parameter_count); | 
| 1805 | 1809 | 
| 1806   // Printing support. | 1810   // Printing support. | 
| 1807   virtual void PrintTo(BufferFormatter* f) const = 0; | 1811   virtual void PrintTo(BufferFormatter* f) const = 0; | 
| 1808   virtual void PrintToVisualizer(BufferFormatter* f) const = 0; | 1812   virtual void PrintToVisualizer(BufferFormatter* f) const = 0; | 
| 1809 | 1813 | 
| 1810 #define INSTRUCTION_TYPE_CHECK(type)                                           \ | 1814 #define INSTRUCTION_TYPE_CHECK(type)                                           \ | 
| 1811   virtual bool Is##type() const { return false; }                              \ | 1815   virtual bool Is##type() const { return false; }                              \ | 
| 1812   virtual type##Instr* As##type() { return NULL; } | 1816   virtual type##Instr* As##type() { return NULL; } | 
| 1813 FOR_EACH_INSTRUCTION(INSTRUCTION_TYPE_CHECK) | 1817 FOR_EACH_INSTRUCTION(INSTRUCTION_TYPE_CHECK) | 
| 1814 #undef INSTRUCTION_TYPE_CHECK | 1818 #undef INSTRUCTION_TYPE_CHECK | 
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1911 | 1915 | 
| 1912   Instruction* last_instruction() const { return last_instruction_; } | 1916   Instruction* last_instruction() const { return last_instruction_; } | 
| 1913   void set_last_instruction(Instruction* instr) { last_instruction_ = instr; } | 1917   void set_last_instruction(Instruction* instr) { last_instruction_ = instr; } | 
| 1914 | 1918 | 
| 1915   virtual void DiscoverBlocks( | 1919   virtual void DiscoverBlocks( | 
| 1916       BlockEntryInstr* current_block, | 1920       BlockEntryInstr* current_block, | 
| 1917       GrowableArray<BlockEntryInstr*>* preorder, | 1921       GrowableArray<BlockEntryInstr*>* preorder, | 
| 1918       GrowableArray<BlockEntryInstr*>* postorder, | 1922       GrowableArray<BlockEntryInstr*>* postorder, | 
| 1919       GrowableArray<intptr_t>* parent, | 1923       GrowableArray<intptr_t>* parent, | 
| 1920       GrowableArray<BitVector*>* assigned_vars, | 1924       GrowableArray<BitVector*>* assigned_vars, | 
| 1921       intptr_t variable_count); | 1925       intptr_t variable_count, | 
|  | 1926       intptr_t fixed_parameter_count); | 
| 1922 | 1927 | 
| 1923  protected: | 1928  protected: | 
| 1924   BlockEntryInstr() | 1929   BlockEntryInstr() | 
| 1925       : preorder_number_(-1), | 1930       : preorder_number_(-1), | 
| 1926         postorder_number_(-1), | 1931         postorder_number_(-1), | 
| 1927         block_id_(-1), | 1932         block_id_(-1), | 
| 1928         dominator_(NULL), | 1933         dominator_(NULL), | 
| 1929         dominated_blocks_(1), | 1934         dominated_blocks_(1), | 
| 1930         last_instruction_(NULL) { } | 1935         last_instruction_(NULL) { } | 
| 1931 | 1936 | 
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1993   Instruction* current_; | 1998   Instruction* current_; | 
| 1994 }; | 1999 }; | 
| 1995 | 2000 | 
| 1996 | 2001 | 
| 1997 class GraphEntryInstr : public BlockEntryInstr { | 2002 class GraphEntryInstr : public BlockEntryInstr { | 
| 1998  public: | 2003  public: | 
| 1999   explicit GraphEntryInstr(TargetEntryInstr* normal_entry) | 2004   explicit GraphEntryInstr(TargetEntryInstr* normal_entry) | 
| 2000       : BlockEntryInstr(), | 2005       : BlockEntryInstr(), | 
| 2001         normal_entry_(normal_entry), | 2006         normal_entry_(normal_entry), | 
| 2002         catch_entries_(), | 2007         catch_entries_(), | 
| 2003         start_env_(NULL) { } | 2008         start_env_(NULL), | 
|  | 2009         spill_slot_count_(0) { } | 
| 2004 | 2010 | 
| 2005   DECLARE_INSTRUCTION(GraphEntry) | 2011   DECLARE_INSTRUCTION(GraphEntry) | 
| 2006 | 2012 | 
| 2007   virtual intptr_t PredecessorCount() const { return 0; } | 2013   virtual intptr_t PredecessorCount() const { return 0; } | 
| 2008   virtual BlockEntryInstr* PredecessorAt(intptr_t index) const { | 2014   virtual BlockEntryInstr* PredecessorAt(intptr_t index) const { | 
| 2009     UNREACHABLE(); | 2015     UNREACHABLE(); | 
| 2010     return NULL; | 2016     return NULL; | 
| 2011   } | 2017   } | 
| 2012   virtual void AddPredecessor(BlockEntryInstr* predecessor) { UNREACHABLE(); } | 2018   virtual void AddPredecessor(BlockEntryInstr* predecessor) { UNREACHABLE(); } | 
| 2013 | 2019 | 
| 2014   virtual intptr_t SuccessorCount() const; | 2020   virtual intptr_t SuccessorCount() const; | 
| 2015   virtual BlockEntryInstr* SuccessorAt(intptr_t index) const; | 2021   virtual BlockEntryInstr* SuccessorAt(intptr_t index) const; | 
| 2016 | 2022 | 
| 2017   virtual void DiscoverBlocks( | 2023   virtual void DiscoverBlocks( | 
| 2018       BlockEntryInstr* current_block, | 2024       BlockEntryInstr* current_block, | 
| 2019       GrowableArray<BlockEntryInstr*>* preorder, | 2025       GrowableArray<BlockEntryInstr*>* preorder, | 
| 2020       GrowableArray<BlockEntryInstr*>* postorder, | 2026       GrowableArray<BlockEntryInstr*>* postorder, | 
| 2021       GrowableArray<intptr_t>* parent, | 2027       GrowableArray<intptr_t>* parent, | 
| 2022       GrowableArray<BitVector*>* assigned_vars, | 2028       GrowableArray<BitVector*>* assigned_vars, | 
| 2023       intptr_t variable_count); | 2029       intptr_t variable_count, | 
|  | 2030       intptr_t fixed_parameter_count); | 
| 2024 | 2031 | 
| 2025   void AddCatchEntry(TargetEntryInstr* entry) { catch_entries_.Add(entry); } | 2032   void AddCatchEntry(TargetEntryInstr* entry) { catch_entries_.Add(entry); } | 
| 2026 | 2033 | 
| 2027   virtual void PrepareEntry(FlowGraphCompiler* compiler); | 2034   virtual void PrepareEntry(FlowGraphCompiler* compiler); | 
| 2028 | 2035 | 
| 2029   Environment* start_env() const { return start_env_; } | 2036   Environment* start_env() const { return start_env_; } | 
| 2030   void set_start_env(Environment* env) { start_env_ = env; } | 2037   void set_start_env(Environment* env) { start_env_ = env; } | 
| 2031 | 2038 | 
|  | 2039   intptr_t spill_slot_count() const { return spill_slot_count_; } | 
|  | 2040   void set_spill_slot_count(intptr_t count) { | 
|  | 2041     ASSERT(count >= 0); | 
|  | 2042     spill_slot_count_ = count; | 
|  | 2043   } | 
|  | 2044 | 
| 2032  private: | 2045  private: | 
| 2033   TargetEntryInstr* normal_entry_; | 2046   TargetEntryInstr* normal_entry_; | 
| 2034   GrowableArray<TargetEntryInstr*> catch_entries_; | 2047   GrowableArray<TargetEntryInstr*> catch_entries_; | 
| 2035   Environment* start_env_; | 2048   Environment* start_env_; | 
|  | 2049   intptr_t spill_slot_count_; | 
| 2036 | 2050 | 
| 2037   DISALLOW_COPY_AND_ASSIGN(GraphEntryInstr); | 2051   DISALLOW_COPY_AND_ASSIGN(GraphEntryInstr); | 
| 2038 }; | 2052 }; | 
| 2039 | 2053 | 
| 2040 | 2054 | 
| 2041 class JoinEntryInstr : public BlockEntryInstr { | 2055 class JoinEntryInstr : public BlockEntryInstr { | 
| 2042  public: | 2056  public: | 
| 2043   JoinEntryInstr() | 2057   JoinEntryInstr() | 
| 2044       : BlockEntryInstr(), | 2058       : BlockEntryInstr(), | 
| 2045         predecessors_(2),  // Two is the assumed to be the common case. | 2059         predecessors_(2),  // Two is the assumed to be the common case. | 
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 2168 | 2182 | 
| 2169   Computation* computation() const { return computation_; } | 2183   Computation* computation() const { return computation_; } | 
| 2170   void set_computation(Computation* value) { computation_ = value; } | 2184   void set_computation(Computation* value) { computation_ = value; } | 
| 2171   bool is_used() const { return is_used_; } | 2185   bool is_used() const { return is_used_; } | 
| 2172 | 2186 | 
| 2173   // Static type of the underlying computation. | 2187   // Static type of the underlying computation. | 
| 2174   virtual RawAbstractType* StaticType() const { | 2188   virtual RawAbstractType* StaticType() const { | 
| 2175     return computation()->StaticType(); | 2189     return computation()->StaticType(); | 
| 2176   } | 2190   } | 
| 2177 | 2191 | 
| 2178   virtual void RecordAssignedVars(BitVector* assigned_vars); | 2192   virtual void RecordAssignedVars(BitVector* assigned_vars, | 
|  | 2193                                   intptr_t fixed_parameter_count); | 
| 2179 | 2194 | 
| 2180   virtual LocationSummary* locs() { | 2195   virtual LocationSummary* locs() { | 
| 2181     return computation()->locs(); | 2196     return computation()->locs(); | 
| 2182   } | 2197   } | 
| 2183 | 2198 | 
| 2184   virtual void EmitNativeCode(FlowGraphCompiler* compiler); | 2199   virtual void EmitNativeCode(FlowGraphCompiler* compiler); | 
| 2185 | 2200 | 
| 2186  private: | 2201  private: | 
| 2187   Computation* computation_; | 2202   Computation* computation_; | 
| 2188   const bool is_used_; | 2203   const bool is_used_; | 
| (...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 2378 | 2393 | 
| 2379   virtual intptr_t SuccessorCount() const; | 2394   virtual intptr_t SuccessorCount() const; | 
| 2380   virtual BlockEntryInstr* SuccessorAt(intptr_t index) const; | 2395   virtual BlockEntryInstr* SuccessorAt(intptr_t index) const; | 
| 2381 | 2396 | 
| 2382   virtual void DiscoverBlocks( | 2397   virtual void DiscoverBlocks( | 
| 2383       BlockEntryInstr* current_block, | 2398       BlockEntryInstr* current_block, | 
| 2384       GrowableArray<BlockEntryInstr*>* preorder, | 2399       GrowableArray<BlockEntryInstr*>* preorder, | 
| 2385       GrowableArray<BlockEntryInstr*>* postorder, | 2400       GrowableArray<BlockEntryInstr*>* postorder, | 
| 2386       GrowableArray<intptr_t>* parent, | 2401       GrowableArray<intptr_t>* parent, | 
| 2387       GrowableArray<BitVector*>* assigned_vars, | 2402       GrowableArray<BitVector*>* assigned_vars, | 
| 2388       intptr_t variable_count); | 2403       intptr_t variable_count, | 
|  | 2404       intptr_t fixed_parameter_count); | 
| 2389 | 2405 | 
| 2390   virtual LocationSummary* MakeLocationSummary() const; | 2406   virtual LocationSummary* MakeLocationSummary() const; | 
| 2391 | 2407 | 
| 2392   virtual void EmitNativeCode(FlowGraphCompiler* compiler); | 2408   virtual void EmitNativeCode(FlowGraphCompiler* compiler); | 
| 2393 | 2409 | 
| 2394   void EmitBranchOnCondition(FlowGraphCompiler* compiler, | 2410   void EmitBranchOnCondition(FlowGraphCompiler* compiler, | 
| 2395                              Condition true_condition); | 2411                              Condition true_condition); | 
| 2396 | 2412 | 
| 2397  private: | 2413  private: | 
| 2398   const intptr_t token_pos_; | 2414   const intptr_t token_pos_; | 
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 2493 | 2509 | 
| 2494 #undef DECLARE_INSTRUCTION | 2510 #undef DECLARE_INSTRUCTION | 
| 2495 | 2511 | 
| 2496 | 2512 | 
| 2497 class Environment : public ZoneAllocated { | 2513 class Environment : public ZoneAllocated { | 
| 2498  public: | 2514  public: | 
| 2499   // Construct an environment by copying from an array of values. | 2515   // Construct an environment by copying from an array of values. | 
| 2500   // TODO(vegorov): it's absolutely crucial that locations_ backing store | 2516   // TODO(vegorov): it's absolutely crucial that locations_ backing store | 
| 2501   // is preallocated and never reallocated.  We use pointers into it | 2517   // is preallocated and never reallocated.  We use pointers into it | 
| 2502   // during register allocation. | 2518   // during register allocation. | 
| 2503   explicit Environment(const GrowableArray<Value*>& values) | 2519   explicit Environment(const GrowableArray<Value*>& values, | 
| 2504       : values_(values.length()), locations_(values.length()) { | 2520                        intptr_t fixed_parameter_count) | 
|  | 2521       : values_(values.length()), | 
|  | 2522         locations_(values.length()), | 
|  | 2523         fixed_parameter_count_(fixed_parameter_count) { | 
| 2505     values_.AddArray(values); | 2524     values_.AddArray(values); | 
| 2506   } | 2525   } | 
| 2507 | 2526 | 
| 2508   const GrowableArray<Value*>& values() const { | 2527   const GrowableArray<Value*>& values() const { | 
| 2509     return values_; | 2528     return values_; | 
| 2510   } | 2529   } | 
| 2511 | 2530 | 
| 2512   void AddLocation(Location value) { | 2531   void AddLocation(Location value) { | 
| 2513     locations_.Add(value); | 2532     locations_.Add(value); | 
| 2514   } | 2533   } | 
| 2515 | 2534 | 
| 2516   Location LocationAt(intptr_t ix) const { | 2535   Location LocationAt(intptr_t ix) const { | 
| 2517     return locations_[ix]; | 2536     return locations_[ix]; | 
| 2518   } | 2537   } | 
| 2519 | 2538 | 
| 2520   Location* LocationSlotAt(intptr_t ix) const { | 2539   Location* LocationSlotAt(intptr_t ix) const { | 
| 2521     return & locations_[ix]; | 2540     return & locations_[ix]; | 
| 2522   } | 2541   } | 
| 2523 | 2542 | 
|  | 2543   intptr_t fixed_parameter_count() const { | 
|  | 2544     return fixed_parameter_count_; | 
|  | 2545   } | 
|  | 2546 | 
| 2524   void PrintTo(BufferFormatter* f) const; | 2547   void PrintTo(BufferFormatter* f) const; | 
| 2525 | 2548 | 
| 2526  private: | 2549  private: | 
| 2527   GrowableArray<Value*> values_; | 2550   GrowableArray<Value*> values_; | 
| 2528   GrowableArray<Location> locations_; | 2551   GrowableArray<Location> locations_; | 
|  | 2552   const intptr_t fixed_parameter_count_; | 
|  | 2553 | 
| 2529   DISALLOW_COPY_AND_ASSIGN(Environment); | 2554   DISALLOW_COPY_AND_ASSIGN(Environment); | 
| 2530 }; | 2555 }; | 
| 2531 | 2556 | 
| 2532 | 2557 | 
| 2533 // Visitor base class to visit each instruction and computation in a flow | 2558 // Visitor base class to visit each instruction and computation in a flow | 
| 2534 // graph as defined by a reversed list of basic blocks. | 2559 // graph as defined by a reversed list of basic blocks. | 
| 2535 class FlowGraphVisitor : public ValueObject { | 2560 class FlowGraphVisitor : public ValueObject { | 
| 2536  public: | 2561  public: | 
| 2537   explicit FlowGraphVisitor(const GrowableArray<BlockEntryInstr*>& block_order) | 2562   explicit FlowGraphVisitor(const GrowableArray<BlockEntryInstr*>& block_order) | 
| 2538       : block_order_(block_order) { } | 2563       : block_order_(block_order) { } | 
| (...skipping 21 matching lines...) Expand all  Loading... | 
| 2560   const GrowableArray<BlockEntryInstr*>& block_order_; | 2585   const GrowableArray<BlockEntryInstr*>& block_order_; | 
| 2561 | 2586 | 
| 2562  private: | 2587  private: | 
| 2563   DISALLOW_COPY_AND_ASSIGN(FlowGraphVisitor); | 2588   DISALLOW_COPY_AND_ASSIGN(FlowGraphVisitor); | 
| 2564 }; | 2589 }; | 
| 2565 | 2590 | 
| 2566 | 2591 | 
| 2567 }  // namespace dart | 2592 }  // namespace dart | 
| 2568 | 2593 | 
| 2569 #endif  // VM_INTERMEDIATE_LANGUAGE_H_ | 2594 #endif  // VM_INTERMEDIATE_LANGUAGE_H_ | 
| OLD | NEW | 
|---|