| OLD | NEW |
| 1 //===- subzero/src/IceGlobalInits.h - Global declarations -------*- C++ -*-===// | 1 //===- subzero/src/IceGlobalInits.h - Global declarations -------*- C++ -*-===// |
| 2 // | 2 // |
| 3 // The Subzero Code Generator | 3 // The Subzero Code Generator |
| 4 // | 4 // |
| 5 // This file is distributed under the University of Illinois Open Source | 5 // This file is distributed under the University of Illinois Open Source |
| 6 // License. See LICENSE.TXT for details. | 6 // License. See LICENSE.TXT for details. |
| 7 // | 7 // |
| 8 //===----------------------------------------------------------------------===// | 8 //===----------------------------------------------------------------------===// |
| 9 // | 9 // |
| 10 // This file declares the representation of function declarations, | 10 // This file declares the representation of function declarations, |
| 11 // global variable declarations, and the corresponding variable | 11 // global variable declarations, and the corresponding variable |
| 12 // initializers in Subzero. Global variable initializers are | 12 // initializers in Subzero. Global variable initializers are |
| 13 // represented as a sequence of simple initializers. | 13 // represented as a sequence of simple initializers. |
| 14 // | 14 // |
| 15 //===----------------------------------------------------------------------===// | 15 //===----------------------------------------------------------------------===// |
| 16 | 16 |
| 17 #ifndef SUBZERO_SRC_ICEGLOBALINITS_H | 17 #ifndef SUBZERO_SRC_ICEGLOBALINITS_H |
| 18 #define SUBZERO_SRC_ICEGLOBALINITS_H | 18 #define SUBZERO_SRC_ICEGLOBALINITS_H |
| 19 | 19 |
| 20 #include <memory> |
| 21 #include <utility> |
| 22 |
| 23 #include "llvm/Bitcode/NaCl/NaClBitcodeParser.h" // for NaClBitcodeRecord. |
| 20 #include "llvm/IR/CallingConv.h" | 24 #include "llvm/IR/CallingConv.h" |
| 21 #include "llvm/IR/GlobalValue.h" // for GlobalValue::LinkageTypes | 25 #include "llvm/IR/GlobalValue.h" // for GlobalValue::LinkageTypes. |
| 22 | 26 |
| 23 #include "IceDefs.h" | 27 #include "IceDefs.h" |
| 24 #include "IceTypes.h" | 28 #include "IceTypes.h" |
| 25 | 29 |
| 26 // TODO(kschimpf): Remove ourselves from using LLVM representation for calling | 30 // TODO(kschimpf): Remove ourselves from using LLVM representation for calling |
| 27 // conventions and linkage types. | 31 // conventions and linkage types. |
| 28 | 32 |
| 29 namespace Ice { | 33 namespace Ice { |
| 30 | 34 |
| 31 /// Base class for global variable and function declarations. | 35 /// Base class for global variable and function declarations. |
| (...skipping 15 matching lines...) Expand all Loading... |
| 47 bool isInternal() const { | 51 bool isInternal() const { |
| 48 return Linkage == llvm::GlobalValue::InternalLinkage; | 52 return Linkage == llvm::GlobalValue::InternalLinkage; |
| 49 } | 53 } |
| 50 llvm::GlobalValue::LinkageTypes getLinkage() const { return Linkage; } | 54 llvm::GlobalValue::LinkageTypes getLinkage() const { return Linkage; } |
| 51 bool isExternal() const { | 55 bool isExternal() const { |
| 52 return Linkage == llvm::GlobalValue::ExternalLinkage; | 56 return Linkage == llvm::GlobalValue::ExternalLinkage; |
| 53 } | 57 } |
| 54 void setLinkage(llvm::GlobalValue::LinkageTypes NewLinkage) { | 58 void setLinkage(llvm::GlobalValue::LinkageTypes NewLinkage) { |
| 55 Linkage = NewLinkage; | 59 Linkage = NewLinkage; |
| 56 } | 60 } |
| 57 virtual ~GlobalDeclaration() {} | 61 virtual ~GlobalDeclaration() = default; |
| 58 | 62 |
| 59 /// Prints out type of the global declaration. | 63 /// Prints out type of the global declaration. |
| 60 virtual void dumpType(Ostream &Stream) const = 0; | 64 virtual void dumpType(Ostream &Stream) const = 0; |
| 61 | 65 |
| 62 /// Prints out the global declaration. | 66 /// Prints out the global declaration. |
| 63 virtual void dump(GlobalContext *Ctx, Ostream &Stream) const = 0; | 67 virtual void dump(GlobalContext *Ctx, Ostream &Stream) const = 0; |
| 64 void dump(Ostream &Stream) const { | 68 void dump(Ostream &Stream) const { |
| 65 if (!ALLOW_DUMP) | 69 if (!ALLOW_DUMP) |
| 66 return; | 70 return; |
| 67 GlobalContext *const Ctx = nullptr; | 71 GlobalContext *const Ctx = nullptr; |
| (...skipping 20 matching lines...) Expand all Loading... |
| 88 }; | 92 }; |
| 89 | 93 |
| 90 // Models a function declaration. This includes the type signature of | 94 // Models a function declaration. This includes the type signature of |
| 91 // the function, its calling conventions, and its linkage. | 95 // the function, its calling conventions, and its linkage. |
| 92 class FunctionDeclaration : public GlobalDeclaration { | 96 class FunctionDeclaration : public GlobalDeclaration { |
| 93 FunctionDeclaration() = delete; | 97 FunctionDeclaration() = delete; |
| 94 FunctionDeclaration(const FunctionDeclaration &) = delete; | 98 FunctionDeclaration(const FunctionDeclaration &) = delete; |
| 95 FunctionDeclaration &operator=(const FunctionDeclaration &) = delete; | 99 FunctionDeclaration &operator=(const FunctionDeclaration &) = delete; |
| 96 | 100 |
| 97 public: | 101 public: |
| 98 static FunctionDeclaration *create(const FuncSigType &Signature, | 102 static FunctionDeclaration *create(GlobalContext *Context, |
| 103 const FuncSigType &Signature, |
| 99 llvm::CallingConv::ID CallingConv, | 104 llvm::CallingConv::ID CallingConv, |
| 100 llvm::GlobalValue::LinkageTypes Linkage, | 105 llvm::GlobalValue::LinkageTypes Linkage, |
| 101 bool IsProto); | 106 bool IsProto) { |
| 102 ~FunctionDeclaration() final {} | 107 return new (Context->allocate<FunctionDeclaration>()) |
| 108 FunctionDeclaration(Signature, CallingConv, Linkage, IsProto); |
| 109 } |
| 103 const FuncSigType &getSignature() const { return Signature; } | 110 const FuncSigType &getSignature() const { return Signature; } |
| 104 llvm::CallingConv::ID getCallingConv() const { return CallingConv; } | 111 llvm::CallingConv::ID getCallingConv() const { return CallingConv; } |
| 105 // isProto implies that there isn't a (local) definition for the function. | 112 // isProto implies that there isn't a (local) definition for the function. |
| 106 bool isProto() const { return IsProto; } | 113 bool isProto() const { return IsProto; } |
| 107 static bool classof(const GlobalDeclaration *Addr) { | 114 static bool classof(const GlobalDeclaration *Addr) { |
| 108 return Addr->getKind() == FunctionDeclarationKind; | 115 return Addr->getKind() == FunctionDeclarationKind; |
| 109 } | 116 } |
| 110 void dumpType(Ostream &Stream) const final; | 117 void dumpType(Ostream &Stream) const final; |
| 111 void dump(GlobalContext *Ctx, Ostream &Stream) const final; | 118 void dump(GlobalContext *Ctx, Ostream &Stream) const final; |
| 112 bool getSuppressMangling() const final { return isExternal() && IsProto; } | 119 bool getSuppressMangling() const final { return isExternal() && IsProto; } |
| (...skipping 22 matching lines...) Expand all Loading... |
| 135 Initializer &operator=(const Initializer &) = delete; | 142 Initializer &operator=(const Initializer &) = delete; |
| 136 | 143 |
| 137 public: | 144 public: |
| 138 /// Discriminator for LLVM-style RTTI. | 145 /// Discriminator for LLVM-style RTTI. |
| 139 enum InitializerKind { | 146 enum InitializerKind { |
| 140 DataInitializerKind, | 147 DataInitializerKind, |
| 141 ZeroInitializerKind, | 148 ZeroInitializerKind, |
| 142 RelocInitializerKind | 149 RelocInitializerKind |
| 143 }; | 150 }; |
| 144 InitializerKind getKind() const { return Kind; } | 151 InitializerKind getKind() const { return Kind; } |
| 145 virtual ~Initializer() {} | 152 virtual ~Initializer() = default; |
| 146 virtual SizeT getNumBytes() const = 0; | 153 virtual SizeT getNumBytes() const = 0; |
| 147 virtual void dump(GlobalContext *Ctx, Ostream &Stream) const = 0; | 154 virtual void dump(GlobalContext *Ctx, Ostream &Stream) const = 0; |
| 148 void dump(Ostream &Stream) const { | 155 void dump(Ostream &Stream) const { |
| 149 if (ALLOW_DUMP) | 156 if (ALLOW_DUMP) |
| 150 dump(nullptr, Stream); | 157 dump(nullptr, Stream); |
| 151 } | 158 } |
| 152 virtual void dumpType(Ostream &Stream) const; | 159 virtual void dumpType(Ostream &Stream) const; |
| 153 | 160 |
| 154 protected: | 161 protected: |
| 155 explicit Initializer(InitializerKind Kind) : Kind(Kind) {} | 162 explicit Initializer(InitializerKind Kind) : Kind(Kind) {} |
| 156 | 163 |
| 157 private: | 164 private: |
| 158 const InitializerKind Kind; | 165 const InitializerKind Kind; |
| 159 }; | 166 }; |
| 160 | 167 |
| 161 // Models the data in a data initializer. | 168 // Models the data in a data initializer. |
| 162 typedef std::vector<char> DataVecType; | 169 typedef std::vector<char> DataVecType; |
| 163 | 170 |
| 164 /// Defines a sequence of byte values as a data initializer. | 171 /// Defines a sequence of byte values as a data initializer. |
| 165 class DataInitializer : public Initializer { | 172 class DataInitializer : public Initializer { |
| 166 DataInitializer(const DataInitializer &) = delete; | 173 DataInitializer(const DataInitializer &) = delete; |
| 167 DataInitializer &operator=(const DataInitializer &) = delete; | 174 DataInitializer &operator=(const DataInitializer &) = delete; |
| 168 | 175 |
| 169 public: | 176 public: |
| 170 template <class IntContainer> | 177 template <class... Args> |
| 171 DataInitializer(const IntContainer &Values) | 178 static std::unique_ptr<DataInitializer> create(Args &&... TheArgs) { |
| 172 : Initializer(DataInitializerKind), Contents(Values.size()) { | 179 return makeUnique<DataInitializer>(std::forward<Args>(TheArgs)...); |
| 173 size_t i = 0; | |
| 174 for (auto &V : Values) { | |
| 175 Contents[i] = static_cast<int8_t>(V); | |
| 176 ++i; | |
| 177 } | |
| 178 } | 180 } |
| 179 DataInitializer(const char *Str, size_t StrLen) | 181 |
| 180 : Initializer(DataInitializerKind), Contents(StrLen) { | |
| 181 for (size_t i = 0; i < StrLen; ++i) | |
| 182 Contents[i] = Str[i]; | |
| 183 } | |
| 184 ~DataInitializer() override {} | |
| 185 const DataVecType &getContents() const { return Contents; } | 182 const DataVecType &getContents() const { return Contents; } |
| 186 SizeT getNumBytes() const final { return Contents.size(); } | 183 SizeT getNumBytes() const final { return Contents.size(); } |
| 187 void dump(GlobalContext *Ctx, Ostream &Stream) const final; | 184 void dump(GlobalContext *Ctx, Ostream &Stream) const final; |
| 188 static bool classof(const Initializer *D) { | 185 static bool classof(const Initializer *D) { |
| 189 return D->getKind() == DataInitializerKind; | 186 return D->getKind() == DataInitializerKind; |
| 190 } | 187 } |
| 191 | 188 |
| 192 private: | 189 private: |
| 190 ENABLE_MAKE_UNIQUE; |
| 191 |
| 192 DataInitializer(const llvm::NaClBitcodeRecord::RecordVector &Values) |
| 193 : Initializer(DataInitializerKind), Contents(Values.size()) { |
| 194 for (SizeT I = 0; I < Values.size(); ++I) |
| 195 Contents[I] = static_cast<int8_t>(Values[I]); |
| 196 } |
| 197 |
| 198 DataInitializer(const char *Str, size_t StrLen) |
| 199 : Initializer(DataInitializerKind), Contents(StrLen) { |
| 200 for (size_t i = 0; i < StrLen; ++i) |
| 201 Contents[i] = Str[i]; |
| 202 } |
| 203 |
| 193 // The byte contents of the data initializer. | 204 // The byte contents of the data initializer. |
| 194 DataVecType Contents; | 205 DataVecType Contents; |
| 195 }; | 206 }; |
| 196 | 207 |
| 197 /// Defines a sequence of bytes initialized to zero. | 208 /// Defines a sequence of bytes initialized to zero. |
| 198 class ZeroInitializer : public Initializer { | 209 class ZeroInitializer : public Initializer { |
| 199 ZeroInitializer(const ZeroInitializer &) = delete; | 210 ZeroInitializer(const ZeroInitializer &) = delete; |
| 200 ZeroInitializer &operator=(const ZeroInitializer &) = delete; | 211 ZeroInitializer &operator=(const ZeroInitializer &) = delete; |
| 201 | 212 |
| 202 public: | 213 public: |
| 203 explicit ZeroInitializer(SizeT Size) | 214 static std::unique_ptr<ZeroInitializer> create(SizeT Size) { |
| 204 : Initializer(ZeroInitializerKind), Size(Size) {} | 215 return makeUnique<ZeroInitializer>(Size); |
| 205 ~ZeroInitializer() override {} | 216 } |
| 206 SizeT getNumBytes() const final { return Size; } | 217 SizeT getNumBytes() const final { return Size; } |
| 207 void dump(GlobalContext *Ctx, Ostream &Stream) const final; | 218 void dump(GlobalContext *Ctx, Ostream &Stream) const final; |
| 208 static bool classof(const Initializer *Z) { | 219 static bool classof(const Initializer *Z) { |
| 209 return Z->getKind() == ZeroInitializerKind; | 220 return Z->getKind() == ZeroInitializerKind; |
| 210 } | 221 } |
| 211 | 222 |
| 212 private: | 223 private: |
| 224 ENABLE_MAKE_UNIQUE; |
| 225 |
| 226 explicit ZeroInitializer(SizeT Size) |
| 227 : Initializer(ZeroInitializerKind), Size(Size) {} |
| 228 |
| 213 // The number of bytes to be zero initialized. | 229 // The number of bytes to be zero initialized. |
| 214 SizeT Size; | 230 SizeT Size; |
| 215 }; | 231 }; |
| 216 | 232 |
| 217 /// Defines the relocation value of another global declaration. | 233 /// Defines the relocation value of another global declaration. |
| 218 class RelocInitializer : public Initializer { | 234 class RelocInitializer : public Initializer { |
| 219 RelocInitializer(const RelocInitializer &) = delete; | 235 RelocInitializer(const RelocInitializer &) = delete; |
| 220 RelocInitializer &operator=(const RelocInitializer &) = delete; | 236 RelocInitializer &operator=(const RelocInitializer &) = delete; |
| 221 | 237 |
| 222 public: | 238 public: |
| 223 RelocInitializer(const GlobalDeclaration *Declaration, RelocOffsetT Offset) | 239 static std::unique_ptr<RelocInitializer> |
| 224 : Initializer(RelocInitializerKind), Declaration(Declaration), | 240 create(const GlobalDeclaration *Declaration, RelocOffsetT Offset) { |
| 225 Offset(Offset) {} | 241 return makeUnique<RelocInitializer>(Declaration, Offset); |
| 226 ~RelocInitializer() override {} | 242 } |
| 243 |
| 227 RelocOffsetT getOffset() const { return Offset; } | 244 RelocOffsetT getOffset() const { return Offset; } |
| 228 const GlobalDeclaration *getDeclaration() const { return Declaration; } | 245 const GlobalDeclaration *getDeclaration() const { return Declaration; } |
| 229 SizeT getNumBytes() const final { return RelocAddrSize; } | 246 SizeT getNumBytes() const final { return RelocAddrSize; } |
| 230 void dump(GlobalContext *Ctx, Ostream &Stream) const final; | 247 void dump(GlobalContext *Ctx, Ostream &Stream) const final; |
| 231 void dumpType(Ostream &Stream) const final; | 248 void dumpType(Ostream &Stream) const final; |
| 232 static bool classof(const Initializer *R) { | 249 static bool classof(const Initializer *R) { |
| 233 return R->getKind() == RelocInitializerKind; | 250 return R->getKind() == RelocInitializerKind; |
| 234 } | 251 } |
| 235 | 252 |
| 236 private: | 253 private: |
| 237 // The global declaration used in the relocation. | 254 ENABLE_MAKE_UNIQUE; |
| 255 |
| 256 RelocInitializer(const GlobalDeclaration *Declaration, RelocOffsetT Offset) |
| 257 : Initializer(RelocInitializerKind), Declaration(Declaration), |
| 258 Offset(Offset) {} // The global declaration used in the relocation. |
| 259 |
| 238 const GlobalDeclaration *Declaration; | 260 const GlobalDeclaration *Declaration; |
| 239 // The offset to add to the relocation. | 261 // The offset to add to the relocation. |
| 240 const RelocOffsetT Offset; | 262 const RelocOffsetT Offset; |
| 241 }; | 263 }; |
| 242 | 264 |
| 243 /// Models the list of initializers. | 265 /// Models the list of initializers. |
| 244 typedef std::vector<Initializer *> InitializerListType; | 266 typedef std::vector<std::unique_ptr<Initializer>> InitializerListType; |
| 245 | 267 |
| 246 static VariableDeclaration *create(); | 268 static VariableDeclaration *create(GlobalContext *Context) { |
| 247 ~VariableDeclaration() final; | 269 return new (Context->allocate<VariableDeclaration>()) VariableDeclaration(); |
| 270 } |
| 248 | 271 |
| 249 const InitializerListType &getInitializers() const { return Initializers; } | 272 const InitializerListType &getInitializers() const { return *Initializers; } |
| 250 bool getIsConstant() const { return IsConstant; } | 273 bool getIsConstant() const { return IsConstant; } |
| 251 void setIsConstant(bool NewValue) { IsConstant = NewValue; } | 274 void setIsConstant(bool NewValue) { IsConstant = NewValue; } |
| 252 uint32_t getAlignment() const { return Alignment; } | 275 uint32_t getAlignment() const { return Alignment; } |
| 253 void setAlignment(uint32_t NewAlignment) { Alignment = NewAlignment; } | 276 void setAlignment(uint32_t NewAlignment) { Alignment = NewAlignment; } |
| 254 bool hasInitializer() const { return !Initializers.empty(); } | 277 bool hasInitializer() const { return HasInitializer; } |
| 255 bool hasNonzeroInitializer() const { | 278 bool hasNonzeroInitializer() const { |
| 256 return !(Initializers.size() == 1 && | 279 return !(Initializers->size() == 1 && |
| 257 llvm::isa<ZeroInitializer>(Initializers[0])); | 280 llvm::isa<ZeroInitializer>((*Initializers)[0].get())); |
| 258 } | 281 } |
| 259 | 282 |
| 260 /// Returns the number of bytes for the initializer of the global | 283 /// Returns the number of bytes for the initializer of the global |
| 261 /// address. | 284 /// address. |
| 262 SizeT getNumBytes() const { | 285 SizeT getNumBytes() const { |
| 263 SizeT Count = 0; | 286 SizeT Count = 0; |
| 264 for (Initializer *Init : Initializers) { | 287 for (const std::unique_ptr<Initializer> &Init : *Initializers) { |
| 265 Count += Init->getNumBytes(); | 288 Count += Init->getNumBytes(); |
| 266 } | 289 } |
| 267 return Count; | 290 return Count; |
| 268 } | 291 } |
| 269 | 292 |
| 270 /// Adds Initializer to the list of initializers. Takes ownership of | 293 /// Adds Initializer to the list of initializers. Takes ownership of |
| 271 /// the initializer. | 294 /// the initializer. |
| 272 void addInitializer(Initializer *Initializer) { | 295 void addInitializer(std::unique_ptr<Initializer> Initializer) { |
| 273 Initializers.push_back(Initializer); | 296 Initializers->emplace_back(std::move(Initializer)); |
| 297 HasInitializer = true; |
| 274 } | 298 } |
| 275 | 299 |
| 276 /// Prints out type for initializer associated with the declaration | 300 /// Prints out type for initializer associated with the declaration |
| 277 /// to Stream. | 301 /// to Stream. |
| 278 void dumpType(Ostream &Stream) const final; | 302 void dumpType(Ostream &Stream) const final; |
| 279 | 303 |
| 280 /// Prints out the definition of the global variable declaration | 304 /// Prints out the definition of the global variable declaration |
| 281 /// (including initialization). | 305 /// (including initialization). |
| 282 void dump(GlobalContext *Ctx, Ostream &Stream) const final; | 306 void dump(GlobalContext *Ctx, Ostream &Stream) const final; |
| 283 | 307 |
| 284 static bool classof(const GlobalDeclaration *Addr) { | 308 static bool classof(const GlobalDeclaration *Addr) { |
| 285 return Addr->getKind() == VariableDeclarationKind; | 309 return Addr->getKind() == VariableDeclarationKind; |
| 286 } | 310 } |
| 287 | 311 |
| 288 bool getSuppressMangling() const final { | 312 bool getSuppressMangling() const final { |
| 289 if (ForceSuppressMangling) | 313 if (ForceSuppressMangling) |
| 290 return true; | 314 return true; |
| 291 return isExternal() && !hasInitializer(); | 315 return isExternal() && !hasInitializer(); |
| 292 } | 316 } |
| 293 | 317 |
| 294 void setSuppressMangling() { ForceSuppressMangling = true; } | 318 void setSuppressMangling() { ForceSuppressMangling = true; } |
| 295 | 319 |
| 320 void discardInitializers() { Initializers = nullptr; } |
| 321 |
| 296 private: | 322 private: |
| 297 // list of initializers for the declared variable. | 323 // list of initializers for the declared variable. |
| 298 InitializerListType Initializers; | 324 std::unique_ptr<InitializerListType> Initializers; |
| 325 bool HasInitializer; |
| 299 // The alignment of the declared variable. | 326 // The alignment of the declared variable. |
| 300 uint32_t Alignment; | 327 uint32_t Alignment; |
| 301 // True if a declared (global) constant. | 328 // True if a declared (global) constant. |
| 302 bool IsConstant; | 329 bool IsConstant; |
| 303 // If set to true, force getSuppressMangling() to return true. | 330 // If set to true, force getSuppressMangling() to return true. |
| 304 bool ForceSuppressMangling; | 331 bool ForceSuppressMangling; |
| 305 | 332 |
| 306 VariableDeclaration() | 333 VariableDeclaration() |
| 307 : GlobalDeclaration(VariableDeclarationKind, | 334 : GlobalDeclaration(VariableDeclarationKind, |
| 308 llvm::GlobalValue::InternalLinkage), | 335 llvm::GlobalValue::InternalLinkage), |
| 336 Initializers(new InitializerListType), HasInitializer(false), |
| 309 Alignment(0), IsConstant(false), ForceSuppressMangling(false) {} | 337 Alignment(0), IsConstant(false), ForceSuppressMangling(false) {} |
| 310 }; | 338 }; |
| 311 | 339 |
| 312 template <class StreamType> | 340 template <class StreamType> |
| 313 inline StreamType &operator<<(StreamType &Stream, | 341 inline StreamType &operator<<(StreamType &Stream, |
| 314 const VariableDeclaration::Initializer &Init) { | 342 const VariableDeclaration::Initializer &Init) { |
| 315 Init.dump(Stream); | 343 Init.dump(Stream); |
| 316 return Stream; | 344 return Stream; |
| 317 } | 345 } |
| 318 | 346 |
| 319 template <class StreamType> | 347 template <class StreamType> |
| 320 inline StreamType &operator<<(StreamType &Stream, | 348 inline StreamType &operator<<(StreamType &Stream, |
| 321 const GlobalDeclaration &Addr) { | 349 const GlobalDeclaration &Addr) { |
| 322 Addr.dump(Stream); | 350 Addr.dump(Stream); |
| 323 return Stream; | 351 return Stream; |
| 324 } | 352 } |
| 325 | 353 |
| 326 } // end of namespace Ice | 354 } // end of namespace Ice |
| 327 | 355 |
| 328 #endif // SUBZERO_SRC_ICEGLOBALINITS_H | 356 #endif // SUBZERO_SRC_ICEGLOBALINITS_H |
| OLD | NEW |