1fd57cecd2cb3ac726942e0101de6a82dc5a958a6Chris Lattner//===-- Bitcode/Writer/ValueEnumerator.h - Number values --------*- C++ -*-===// 2fd57cecd2cb3ac726942e0101de6a82dc5a958a6Chris Lattner// 3fd57cecd2cb3ac726942e0101de6a82dc5a958a6Chris Lattner// The LLVM Compiler Infrastructure 4fd57cecd2cb3ac726942e0101de6a82dc5a958a6Chris Lattner// 54ee451de366474b9c228b4e5fa573795a715216dChris Lattner// This file is distributed under the University of Illinois Open Source 64ee451de366474b9c228b4e5fa573795a715216dChris Lattner// License. See LICENSE.TXT for details. 7fd57cecd2cb3ac726942e0101de6a82dc5a958a6Chris Lattner// 8fd57cecd2cb3ac726942e0101de6a82dc5a958a6Chris Lattner//===----------------------------------------------------------------------===// 9fd57cecd2cb3ac726942e0101de6a82dc5a958a6Chris Lattner// 10fd57cecd2cb3ac726942e0101de6a82dc5a958a6Chris Lattner// This class gives values and types Unique ID's. 11fd57cecd2cb3ac726942e0101de6a82dc5a958a6Chris Lattner// 12fd57cecd2cb3ac726942e0101de6a82dc5a958a6Chris Lattner//===----------------------------------------------------------------------===// 13fd57cecd2cb3ac726942e0101de6a82dc5a958a6Chris Lattner 1437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines#ifndef LLVM_LIB_BITCODE_WRITER_VALUEENUMERATOR_H 1537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines#define LLVM_LIB_BITCODE_WRITER_VALUEENUMERATOR_H 16fd57cecd2cb3ac726942e0101de6a82dc5a958a6Chris Lattner 17fd57cecd2cb3ac726942e0101de6a82dc5a958a6Chris Lattner#include "llvm/ADT/DenseMap.h" 186209869f83979319e2e5791382f09b83e54191e0Devang Patel#include "llvm/ADT/SmallVector.h" 19c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines#include "llvm/ADT/UniqueVector.h" 200b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth#include "llvm/IR/Attributes.h" 2137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines#include "llvm/IR/UseListOrder.h" 22fd57cecd2cb3ac726942e0101de6a82dc5a958a6Chris Lattner#include <vector> 23fd57cecd2cb3ac726942e0101de6a82dc5a958a6Chris Lattner 24fd57cecd2cb3ac726942e0101de6a82dc5a958a6Chris Lattnernamespace llvm { 25fd57cecd2cb3ac726942e0101de6a82dc5a958a6Chris Lattner 26fd57cecd2cb3ac726942e0101de6a82dc5a958a6Chris Lattnerclass Type; 27c59c0afd7d24480f5a23d8fd6764ecfd6d4424ccChris Lattnerclass Value; 28e8e0213cc3daa2d0457c22e4c12e6973f21fc942Devang Patelclass Instruction; 29c59c0afd7d24480f5a23d8fd6764ecfd6d4424ccChris Lattnerclass BasicBlock; 30c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hinesclass Comdat; 31fd57cecd2cb3ac726942e0101de6a82dc5a958a6Chris Lattnerclass Function; 32c59c0afd7d24480f5a23d8fd6764ecfd6d4424ccChris Lattnerclass Module; 33ebe69fe11e48d322045d5949c83283927a0d790bStephen Hinesclass Metadata; 34ebe69fe11e48d322045d5949c83283927a0d790bStephen Hinesclass LocalAsMetadata; 356209869f83979319e2e5791382f09b83e54191e0Devang Patelclass MDNode; 368fba578be72dc98497508dec053e966858571f6aDevang Patelclass NamedMDNode; 3799faa3b4ec6d03ac7808fe4ff3fbf3d04e375502Bill Wendlingclass AttributeSet; 38fd57cecd2cb3ac726942e0101de6a82dc5a958a6Chris Lattnerclass ValueSymbolTable; 390386f01e061513094504bc11f8352a40173cada7Devang Patelclass MDSymbolTable; 404e6c03fc3de8885b9a0a0b8069123b86d4834f08Chad Rosierclass raw_ostream; 41fd57cecd2cb3ac726942e0101de6a82dc5a958a6Chris Lattner 42fd57cecd2cb3ac726942e0101de6a82dc5a958a6Chris Lattnerclass ValueEnumerator { 43fd57cecd2cb3ac726942e0101de6a82dc5a958a6Chris Lattnerpublic: 44db125cfaf57cc83e7dd7453de2d509bc8efd0e5eChris Lattner typedef std::vector<Type*> TypeList; 45fd57cecd2cb3ac726942e0101de6a82dc5a958a6Chris Lattner 46fd57cecd2cb3ac726942e0101de6a82dc5a958a6Chris Lattner // For each value, we remember its Value* and occurrence frequency. 47fd57cecd2cb3ac726942e0101de6a82dc5a958a6Chris Lattner typedef std::vector<std::pair<const Value*, unsigned> > ValueList; 4837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines 4937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines UseListOrderStack UseListOrders; 5037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines 51fd57cecd2cb3ac726942e0101de6a82dc5a958a6Chris Lattnerprivate: 52db125cfaf57cc83e7dd7453de2d509bc8efd0e5eChris Lattner typedef DenseMap<Type*, unsigned> TypeMapType; 53fd57cecd2cb3ac726942e0101de6a82dc5a958a6Chris Lattner TypeMapType TypeMap; 542edd22b959f0d8f897cce397730a881c708e474aChris Lattner TypeList Types; 55fd57cecd2cb3ac726942e0101de6a82dc5a958a6Chris Lattner 56fd57cecd2cb3ac726942e0101de6a82dc5a958a6Chris Lattner typedef DenseMap<const Value*, unsigned> ValueMapType; 57fd57cecd2cb3ac726942e0101de6a82dc5a958a6Chris Lattner ValueMapType ValueMap; 582edd22b959f0d8f897cce397730a881c708e474aChris Lattner ValueList Values; 59c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines 60c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines typedef UniqueVector<const Comdat *> ComdatSetType; 61c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines ComdatSetType Comdats; 62c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines 63ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines std::vector<const Metadata *> MDs; 64ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines SmallVector<const LocalAsMetadata *, 8> FunctionLocalMDs; 65ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines typedef DenseMap<const Metadata *, unsigned> MetadataMapType; 66ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines MetadataMapType MDValueMap; 67ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines bool HasMDString; 68ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines bool HasMDLocation; 69ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines bool HasGenericDebugNode; 702c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar bool ShouldPreserveUseListOrder; 71170a15e98dc6900df1ae40d03c5f0622d792fb45Joe Abbey 72e9229a6a9614cbde1bff2bd6ffae3b7336db5702Bill Wendling typedef DenseMap<AttributeSet, unsigned> AttributeGroupMapType; 73e9229a6a9614cbde1bff2bd6ffae3b7336db5702Bill Wendling AttributeGroupMapType AttributeGroupMap; 74e9229a6a9614cbde1bff2bd6ffae3b7336db5702Bill Wendling std::vector<AttributeSet> AttributeGroups; 758c2e77f895301967bf37d04e905fb1f069ec91b2Bill Wendling 76105ea3d49d4a458af8779ae7f144f00d19c4168fBill Wendling typedef DenseMap<AttributeSet, unsigned> AttributeMapType; 770598866c052147c31b808391f58434ce3dbfb838Devang Patel AttributeMapType AttributeMap; 78034b94b17006f51722886b0f2283fb6fb19aca1fBill Wendling std::vector<AttributeSet> Attribute; 79170a15e98dc6900df1ae40d03c5f0622d792fb45Joe Abbey 80837e04a8bf13712a4a8ae279daab65a048b21f7dChris Lattner /// GlobalBasicBlockIDs - This map memoizes the basic block ID's referenced by 81837e04a8bf13712a4a8ae279daab65a048b21f7dChris Lattner /// the "getGlobalBasicBlockID" method. 82837e04a8bf13712a4a8ae279daab65a048b21f7dChris Lattner mutable DenseMap<const BasicBlock*, unsigned> GlobalBasicBlockIDs; 83170a15e98dc6900df1ae40d03c5f0622d792fb45Joe Abbey 84e8e0213cc3daa2d0457c22e4c12e6973f21fc942Devang Patel typedef DenseMap<const Instruction*, unsigned> InstructionMapType; 85e8e0213cc3daa2d0457c22e4c12e6973f21fc942Devang Patel InstructionMapType InstructionMap; 86e8e0213cc3daa2d0457c22e4c12e6973f21fc942Devang Patel unsigned InstructionCount; 87e8e0213cc3daa2d0457c22e4c12e6973f21fc942Devang Patel 88c59c0afd7d24480f5a23d8fd6764ecfd6d4424ccChris Lattner /// BasicBlocks - This contains all the basic blocks for the currently 89c59c0afd7d24480f5a23d8fd6764ecfd6d4424ccChris Lattner /// incorporated function. Their reverse mapping is stored in ValueMap. 90c59c0afd7d24480f5a23d8fd6764ecfd6d4424ccChris Lattner std::vector<const BasicBlock*> BasicBlocks; 91170a15e98dc6900df1ae40d03c5f0622d792fb45Joe Abbey 928d35c79f273b74df1e95b4472620e31e81342037Chris Lattner /// When a function is incorporated, this is the size of the Values list 938d35c79f273b74df1e95b4472620e31e81342037Chris Lattner /// before incorporation. 94b9d0c2a6a0ef5e19b2d30180ce7d6a10ffa1f5c5Chris Lattner unsigned NumModuleValues; 95309b3af547a60bedd74daa2a94ebd3d3ed5f06e9Dan Gohman 96309b3af547a60bedd74daa2a94ebd3d3ed5f06e9Dan Gohman /// When a function is incorporated, this is the size of the MDValues list 97309b3af547a60bedd74daa2a94ebd3d3ed5f06e9Dan Gohman /// before incorporation. 98ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines unsigned NumModuleMDs; 99309b3af547a60bedd74daa2a94ebd3d3ed5f06e9Dan Gohman 100b9d0c2a6a0ef5e19b2d30180ce7d6a10ffa1f5c5Chris Lattner unsigned FirstFuncConstantID; 101b9d0c2a6a0ef5e19b2d30180ce7d6a10ffa1f5c5Chris Lattner unsigned FirstInstID; 10286a1c32e67b23c5e9e42dff9eb86e99ba15bb42fCraig Topper 103ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines ValueEnumerator(const ValueEnumerator &) = delete; 104ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines void operator=(const ValueEnumerator &) = delete; 105fd57cecd2cb3ac726942e0101de6a82dc5a958a6Chris Lattnerpublic: 1062c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar ValueEnumerator(const Module &M, bool ShouldPreserveUseListOrder); 107fd57cecd2cb3ac726942e0101de6a82dc5a958a6Chris Lattner 1084e6c03fc3de8885b9a0a0b8069123b86d4834f08Chad Rosier void dump() const; 1094e6c03fc3de8885b9a0a0b8069123b86d4834f08Chad Rosier void print(raw_ostream &OS, const ValueMapType &Map, const char *Name) const; 110ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines void print(raw_ostream &OS, const MetadataMapType &Map, 111ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines const char *Name) const; 1124e6c03fc3de8885b9a0a0b8069123b86d4834f08Chad Rosier 113d5ac40457b62f37f0abfb1d61064f7c7300e91eeDevang Patel unsigned getValueID(const Value *V) const; 114ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines unsigned getMetadataID(const Metadata *MD) const { 115ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines auto ID = getMetadataOrNullID(MD); 116ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines assert(ID != 0 && "Metadata not in slotcalculator!"); 117ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines return ID - 1; 118ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines } 119ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines unsigned getMetadataOrNullID(const Metadata *MD) const { 120ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines return MDValueMap.lookup(MD); 121ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines } 122ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 123ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines bool hasMDString() const { return HasMDString; } 124ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines bool hasMDLocation() const { return HasMDLocation; } 125ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines bool hasGenericDebugNode() const { return HasGenericDebugNode; } 126d5ac40457b62f37f0abfb1d61064f7c7300e91eeDevang Patel 1272c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar bool shouldPreserveUseListOrder() const { return ShouldPreserveUseListOrder; } 1282c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar 129db125cfaf57cc83e7dd7453de2d509bc8efd0e5eChris Lattner unsigned getTypeID(Type *T) const { 130fd57cecd2cb3ac726942e0101de6a82dc5a958a6Chris Lattner TypeMapType::const_iterator I = TypeMap.find(T); 131fd57cecd2cb3ac726942e0101de6a82dc5a958a6Chris Lattner assert(I != TypeMap.end() && "Type not in ValueEnumerator!"); 132fd57cecd2cb3ac726942e0101de6a82dc5a958a6Chris Lattner return I->second-1; 133fd57cecd2cb3ac726942e0101de6a82dc5a958a6Chris Lattner } 134e8e0213cc3daa2d0457c22e4c12e6973f21fc942Devang Patel 135e8e0213cc3daa2d0457c22e4c12e6973f21fc942Devang Patel unsigned getInstructionID(const Instruction *I) const; 136e8e0213cc3daa2d0457c22e4c12e6973f21fc942Devang Patel void setInstructionID(const Instruction *I); 137e8e0213cc3daa2d0457c22e4c12e6973f21fc942Devang Patel 138e9229a6a9614cbde1bff2bd6ffae3b7336db5702Bill Wendling unsigned getAttributeID(AttributeSet PAL) const { 13958d74910c6b82e622ecbb57d6644d48fec5a5c0fChris Lattner if (PAL.isEmpty()) return 0; // Null maps to zero. 140105ea3d49d4a458af8779ae7f144f00d19c4168fBill Wendling AttributeMapType::const_iterator I = AttributeMap.find(PAL); 1410598866c052147c31b808391f58434ce3dbfb838Devang Patel assert(I != AttributeMap.end() && "Attribute not in ValueEnumerator!"); 14250954f5cba406a88011cc8ade3ceb4235830f907Chris Lattner return I->second; 14350954f5cba406a88011cc8ade3ceb4235830f907Chris Lattner } 144fd57cecd2cb3ac726942e0101de6a82dc5a958a6Chris Lattner 145e9229a6a9614cbde1bff2bd6ffae3b7336db5702Bill Wendling unsigned getAttributeGroupID(AttributeSet PAL) const { 1468c2e77f895301967bf37d04e905fb1f069ec91b2Bill Wendling if (PAL.isEmpty()) return 0; // Null maps to zero. 147e9229a6a9614cbde1bff2bd6ffae3b7336db5702Bill Wendling AttributeGroupMapType::const_iterator I = AttributeGroupMap.find(PAL); 148e9229a6a9614cbde1bff2bd6ffae3b7336db5702Bill Wendling assert(I != AttributeGroupMap.end() && "Attribute not in ValueEnumerator!"); 1498c2e77f895301967bf37d04e905fb1f069ec91b2Bill Wendling return I->second; 1508c2e77f895301967bf37d04e905fb1f069ec91b2Bill Wendling } 1518c2e77f895301967bf37d04e905fb1f069ec91b2Bill Wendling 152b9d0c2a6a0ef5e19b2d30180ce7d6a10ffa1f5c5Chris Lattner /// getFunctionConstantRange - Return the range of values that corresponds to 153b9d0c2a6a0ef5e19b2d30180ce7d6a10ffa1f5c5Chris Lattner /// function-local constants. 154b9d0c2a6a0ef5e19b2d30180ce7d6a10ffa1f5c5Chris Lattner void getFunctionConstantRange(unsigned &Start, unsigned &End) const { 155b9d0c2a6a0ef5e19b2d30180ce7d6a10ffa1f5c5Chris Lattner Start = FirstFuncConstantID; 156b9d0c2a6a0ef5e19b2d30180ce7d6a10ffa1f5c5Chris Lattner End = FirstInstID; 157b9d0c2a6a0ef5e19b2d30180ce7d6a10ffa1f5c5Chris Lattner } 158170a15e98dc6900df1ae40d03c5f0622d792fb45Joe Abbey 1592edd22b959f0d8f897cce397730a881c708e474aChris Lattner const ValueList &getValues() const { return Values; } 160ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines const std::vector<const Metadata *> &getMDs() const { return MDs; } 161ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines const SmallVectorImpl<const LocalAsMetadata *> &getFunctionLocalMDs() const { 1626209869f83979319e2e5791382f09b83e54191e0Devang Patel return FunctionLocalMDs; 1636209869f83979319e2e5791382f09b83e54191e0Devang Patel } 164fd57cecd2cb3ac726942e0101de6a82dc5a958a6Chris Lattner const TypeList &getTypes() const { return Types; } 165c59c0afd7d24480f5a23d8fd6764ecfd6d4424ccChris Lattner const std::vector<const BasicBlock*> &getBasicBlocks() const { 166170a15e98dc6900df1ae40d03c5f0622d792fb45Joe Abbey return BasicBlocks; 167c59c0afd7d24480f5a23d8fd6764ecfd6d4424ccChris Lattner } 16899faa3b4ec6d03ac7808fe4ff3fbf3d04e375502Bill Wendling const std::vector<AttributeSet> &getAttributes() const { 169034b94b17006f51722886b0f2283fb6fb19aca1fBill Wendling return Attribute; 17050954f5cba406a88011cc8ade3ceb4235830f907Chris Lattner } 171e9229a6a9614cbde1bff2bd6ffae3b7336db5702Bill Wendling const std::vector<AttributeSet> &getAttributeGroups() const { 172e9229a6a9614cbde1bff2bd6ffae3b7336db5702Bill Wendling return AttributeGroups; 1738c2e77f895301967bf37d04e905fb1f069ec91b2Bill Wendling } 174170a15e98dc6900df1ae40d03c5f0622d792fb45Joe Abbey 175c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines const ComdatSetType &getComdats() const { return Comdats; } 176c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines unsigned getComdatID(const Comdat *C) const; 177c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines 178837e04a8bf13712a4a8ae279daab65a048b21f7dChris Lattner /// getGlobalBasicBlockID - This returns the function-specific ID for the 179837e04a8bf13712a4a8ae279daab65a048b21f7dChris Lattner /// specified basic block. This is relatively expensive information, so it 180837e04a8bf13712a4a8ae279daab65a048b21f7dChris Lattner /// should only be used by rare constructs such as address-of-label. 181837e04a8bf13712a4a8ae279daab65a048b21f7dChris Lattner unsigned getGlobalBasicBlockID(const BasicBlock *BB) const; 182fd57cecd2cb3ac726942e0101de6a82dc5a958a6Chris Lattner 1836a0c04dff288b7eaa0459cc7419159765bb5a0b9Chad Rosier /// incorporateFunction/purgeFunction - If you'd like to deal with a function, 184fd57cecd2cb3ac726942e0101de6a82dc5a958a6Chris Lattner /// use these two methods to get its data into the ValueEnumerator! 185fd57cecd2cb3ac726942e0101de6a82dc5a958a6Chris Lattner /// 1866a0c04dff288b7eaa0459cc7419159765bb5a0b9Chad Rosier void incorporateFunction(const Function &F); 1876a0c04dff288b7eaa0459cc7419159765bb5a0b9Chad Rosier void purgeFunction(); 188ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines uint64_t computeBitsRequiredForTypeIndicies() const; 189fd57cecd2cb3ac726942e0101de6a82dc5a958a6Chris Lattner 190fd57cecd2cb3ac726942e0101de6a82dc5a958a6Chris Lattnerprivate: 1916da91d3c2c138eb1d9739701a1314ba3580df897Chris Lattner void OptimizeConstants(unsigned CstStart, unsigned CstEnd); 192170a15e98dc6900df1ae40d03c5f0622d792fb45Joe Abbey 193309b3af547a60bedd74daa2a94ebd3d3ed5f06e9Dan Gohman void EnumerateMDNodeOperands(const MDNode *N); 194ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines void EnumerateMetadata(const Metadata *MD); 195ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines void EnumerateFunctionLocalMetadata(const LocalAsMetadata *Local); 1968fba578be72dc98497508dec053e966858571f6aDevang Patel void EnumerateNamedMDNode(const NamedMDNode *NMD); 197d7e6457c3faf6c5530a4c8224e2dfcf91b57093bVictor Hernandez void EnumerateValue(const Value *V); 198db125cfaf57cc83e7dd7453de2d509bc8efd0e5eChris Lattner void EnumerateType(Type *T); 199d7e6457c3faf6c5530a4c8224e2dfcf91b57093bVictor Hernandez void EnumerateOperandType(const Value *V); 200105ea3d49d4a458af8779ae7f144f00d19c4168fBill Wendling void EnumerateAttributes(AttributeSet PAL); 201170a15e98dc6900df1ae40d03c5f0622d792fb45Joe Abbey 202fd57cecd2cb3ac726942e0101de6a82dc5a958a6Chris Lattner void EnumerateValueSymbolTable(const ValueSymbolTable &ST); 20337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines void EnumerateNamedMetadata(const Module &M); 204fd57cecd2cb3ac726942e0101de6a82dc5a958a6Chris Lattner}; 205fd57cecd2cb3ac726942e0101de6a82dc5a958a6Chris Lattner 206fd57cecd2cb3ac726942e0101de6a82dc5a958a6Chris Lattner} // End llvm namespace 207fd57cecd2cb3ac726942e0101de6a82dc5a958a6Chris Lattner 208fd57cecd2cb3ac726942e0101de6a82dc5a958a6Chris Lattner#endif 209