10baa4809a8de135a6a7abe9cd78a86f208c99164Chandler Carruth//===---- llvm/MDBuilder.h - Builder for LLVM metadata ----------*- C++ -*-===// 2e747fadedf8c5b80f1a0d5e84078a4428e06098eDuncan Sands// 3e747fadedf8c5b80f1a0d5e84078a4428e06098eDuncan Sands// The LLVM Compiler Infrastructure 4e747fadedf8c5b80f1a0d5e84078a4428e06098eDuncan Sands// 5e747fadedf8c5b80f1a0d5e84078a4428e06098eDuncan Sands// This file is distributed under the University of Illinois Open Source 6e747fadedf8c5b80f1a0d5e84078a4428e06098eDuncan Sands// License. See LICENSE.TXT for details. 7e747fadedf8c5b80f1a0d5e84078a4428e06098eDuncan Sands// 8e747fadedf8c5b80f1a0d5e84078a4428e06098eDuncan Sands//===----------------------------------------------------------------------===// 9e747fadedf8c5b80f1a0d5e84078a4428e06098eDuncan Sands// 10e747fadedf8c5b80f1a0d5e84078a4428e06098eDuncan Sands// This file defines the MDBuilder class, which is used as a convenient way to 11e747fadedf8c5b80f1a0d5e84078a4428e06098eDuncan Sands// create LLVM metadata with a consistent and simplified interface. 12e747fadedf8c5b80f1a0d5e84078a4428e06098eDuncan Sands// 13e747fadedf8c5b80f1a0d5e84078a4428e06098eDuncan Sands//===----------------------------------------------------------------------===// 14e747fadedf8c5b80f1a0d5e84078a4428e06098eDuncan Sands 15674be02d525d4e24bc6943ed9274958c580bcfbcJakub Staszak#ifndef LLVM_IR_MDBUILDER_H 16674be02d525d4e24bc6943ed9274958c580bcfbcJakub Staszak#define LLVM_IR_MDBUILDER_H 17e747fadedf8c5b80f1a0d5e84078a4428e06098eDuncan Sands 180b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth#include "llvm/IR/Constants.h" 190b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth#include "llvm/IR/DerivedTypes.h" 200b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth#include "llvm/IR/Metadata.h" 21e747fadedf8c5b80f1a0d5e84078a4428e06098eDuncan Sands 22e747fadedf8c5b80f1a0d5e84078a4428e06098eDuncan Sandsnamespace llvm { 23e747fadedf8c5b80f1a0d5e84078a4428e06098eDuncan Sands 24244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszakclass APInt; 25244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszakclass LLVMContext; 26244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak 27244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszakclass MDBuilder { 28244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak LLVMContext &Context; 29244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak 30244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszakpublic: 31244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak MDBuilder(LLVMContext &context) : Context(context) {} 32244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak 33244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak /// \brief Return the given string as metadata. 34244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak MDString *createString(StringRef Str) { 35244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak return MDString::get(Context, Str); 36244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak } 37244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak 38244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak //===------------------------------------------------------------------===// 39244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak // FPMath metadata. 40244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak //===------------------------------------------------------------------===// 41244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak 42244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak /// \brief Return metadata with the given settings. The special value 0.0 43244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak /// for the Accuracy parameter indicates the default (maximal precision) 44244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak /// setting. 45244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak MDNode *createFPMath(float Accuracy) { 46244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak if (Accuracy == 0.0) 47244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak return 0; 48244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak assert(Accuracy > 0.0 && "Invalid fpmath accuracy!"); 49244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak Value *Op = ConstantFP::get(Type::getFloatTy(Context), Accuracy); 50244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak return MDNode::get(Context, Op); 51244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak } 52244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak 53244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak //===------------------------------------------------------------------===// 54244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak // Prof metadata. 55244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak //===------------------------------------------------------------------===// 56244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak 57244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak /// \brief Return metadata containing two branch weights. 58244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak MDNode *createBranchWeights(uint32_t TrueWeight, uint32_t FalseWeight) { 59244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak uint32_t Weights[] = { TrueWeight, FalseWeight }; 60244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak return createBranchWeights(Weights); 61244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak } 62244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak 63244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak /// \brief Return metadata containing a number of branch weights. 64244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak MDNode *createBranchWeights(ArrayRef<uint32_t> Weights) { 65244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak assert(Weights.size() >= 2 && "Need at least two branch weights!"); 66244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak 67244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak SmallVector<Value *, 4> Vals(Weights.size()+1); 68244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak Vals[0] = createString("branch_weights"); 69244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak 70244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak Type *Int32Ty = Type::getInt32Ty(Context); 71244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak for (unsigned i = 0, e = Weights.size(); i != e; ++i) 72244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak Vals[i+1] = ConstantInt::get(Int32Ty, Weights[i]); 73244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak 74244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak return MDNode::get(Context, Vals); 75244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak } 76244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak 77244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak //===------------------------------------------------------------------===// 78244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak // Range metadata. 79244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak //===------------------------------------------------------------------===// 80244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak 81244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak /// \brief Return metadata describing the range [Lo, Hi). 82244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak MDNode *createRange(const APInt &Lo, const APInt &Hi) { 83244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak assert(Lo.getBitWidth() == Hi.getBitWidth() && "Mismatched bitwidths!"); 84244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak // If the range is everything then it is useless. 85244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak if (Hi == Lo) 86244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak return 0; 87244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak 88244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak // Return the range [Lo, Hi). 89244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak Type *Ty = IntegerType::get(Context, Lo.getBitWidth()); 90244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak Value *Range[2] = { ConstantInt::get(Ty, Lo), ConstantInt::get(Ty, Hi) }; 91244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak return MDNode::get(Context, Range); 92244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak } 93244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak 94244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak 95244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak //===------------------------------------------------------------------===// 96244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak // TBAA metadata. 97244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak //===------------------------------------------------------------------===// 98244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak 99244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak /// \brief Return metadata appropriate for a TBAA root node. Each returned 100244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak /// node is distinct from all other metadata and will never be identified 101244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak /// (uniqued) with anything else. 102244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak MDNode *createAnonymousTBAARoot() { 103244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak // To ensure uniqueness the root node is self-referential. 104244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak MDNode *Dummy = MDNode::getTemporary(Context, ArrayRef<Value*>()); 105244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak MDNode *Root = MDNode::get(Context, Dummy); 106244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak // At this point we have 107244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak // !0 = metadata !{} <- dummy 108244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak // !1 = metadata !{metadata !0} <- root 109244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak // Replace the dummy operand with the root node itself and delete the dummy. 110244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak Root->replaceOperandWith(0, Root); 111244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak MDNode::deleteTemporary(Dummy); 112244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak // We now have 113244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak // !1 = metadata !{metadata !1} <- self-referential root 114244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak return Root; 115244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak } 116244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak 117244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak /// \brief Return metadata appropriate for a TBAA root node with the given 118244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak /// name. This may be identified (uniqued) with other roots with the same 119244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak /// name. 120244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak MDNode *createTBAARoot(StringRef Name) { 121244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak return MDNode::get(Context, createString(Name)); 122244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak } 123244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak 124244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak /// \brief Return metadata for a non-root TBAA node with the given name, 125244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak /// parent in the TBAA tree, and value for 'pointsToConstantMemory'. 126244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak MDNode *createTBAANode(StringRef Name, MDNode *Parent, 127244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak bool isConstant = false) { 128244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak if (isConstant) { 129244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak Constant *Flags = ConstantInt::get(Type::getInt64Ty(Context), 1); 130244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak Value *Ops[3] = { createString(Name), Parent, Flags }; 131244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak return MDNode::get(Context, Ops); 132244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak } else { 133244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak Value *Ops[2] = { createString(Name), Parent }; 134244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak return MDNode::get(Context, Ops); 135e747fadedf8c5b80f1a0d5e84078a4428e06098eDuncan Sands } 136244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak } 137244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak 138244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak struct TBAAStructField { 139244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak uint64_t Offset; 140244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak uint64_t Size; 141244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak MDNode *TBAA; 142244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak TBAAStructField(uint64_t Offset, uint64_t Size, MDNode *TBAA) : 143244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak Offset(Offset), Size(Size), TBAA(TBAA) {} 144244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak }; 145656dc6260654a7fa29d223bcaf6aae048669c72dDuncan Sands 146244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak /// \brief Return metadata for a tbaa.struct node with the given 147244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak /// struct field descriptions. 148244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak MDNode *createTBAAStructNode(ArrayRef<TBAAStructField> Fields) { 149244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak SmallVector<Value *, 4> Vals(Fields.size() * 3); 150244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak Type *Int64 = IntegerType::get(Context, 64); 151244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak for (unsigned i = 0, e = Fields.size(); i != e; ++i) { 152244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak Vals[i * 3 + 0] = ConstantInt::get(Int64, Fields[i].Offset); 153244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak Vals[i * 3 + 1] = ConstantInt::get(Int64, Fields[i].Size); 154244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak Vals[i * 3 + 2] = Fields[i].TBAA; 155c91249485527f69cf0d7e7b6dda9d8e6eb46d4b0Dan Gohman } 156244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak return MDNode::get(Context, Vals); 157244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak } 158c91249485527f69cf0d7e7b6dda9d8e6eb46d4b0Dan Gohman 159082bb7cf57e3a7089b8302a7d676fddf0bce276eManman Ren /// \brief Return metadata for a TBAA struct node in the type DAG 160327f0100d1c1aa738d13b45d70eab08d0d2030fbManman Ren /// with the given name, a list of pairs (offset, field type in the type DAG). 161082bb7cf57e3a7089b8302a7d676fddf0bce276eManman Ren MDNode *createTBAAStructTypeNode(StringRef Name, 162a5b314c27a585b979ac9c9da944aa3cec27d22a6Manman Ren ArrayRef<std::pair<MDNode*, uint64_t> > Fields) { 163082bb7cf57e3a7089b8302a7d676fddf0bce276eManman Ren SmallVector<Value *, 4> Ops(Fields.size() * 2 + 1); 164082bb7cf57e3a7089b8302a7d676fddf0bce276eManman Ren Type *Int64 = IntegerType::get(Context, 64); 165082bb7cf57e3a7089b8302a7d676fddf0bce276eManman Ren Ops[0] = createString(Name); 166082bb7cf57e3a7089b8302a7d676fddf0bce276eManman Ren for (unsigned i = 0, e = Fields.size(); i != e; ++i) { 167a5b314c27a585b979ac9c9da944aa3cec27d22a6Manman Ren Ops[i * 2 + 1] = Fields[i].first; 168a5b314c27a585b979ac9c9da944aa3cec27d22a6Manman Ren Ops[i * 2 + 2] = ConstantInt::get(Int64, Fields[i].second); 169082bb7cf57e3a7089b8302a7d676fddf0bce276eManman Ren } 170082bb7cf57e3a7089b8302a7d676fddf0bce276eManman Ren return MDNode::get(Context, Ops); 171082bb7cf57e3a7089b8302a7d676fddf0bce276eManman Ren } 172082bb7cf57e3a7089b8302a7d676fddf0bce276eManman Ren 173327f0100d1c1aa738d13b45d70eab08d0d2030fbManman Ren /// \brief Return metadata for a TBAA scalar type node with the 174327f0100d1c1aa738d13b45d70eab08d0d2030fbManman Ren /// given name, an offset and a parent in the TBAA type DAG. 175a5b314c27a585b979ac9c9da944aa3cec27d22a6Manman Ren MDNode *createTBAAScalarTypeNode(StringRef Name, MDNode *Parent, 176a5b314c27a585b979ac9c9da944aa3cec27d22a6Manman Ren uint64_t Offset = 0) { 177327f0100d1c1aa738d13b45d70eab08d0d2030fbManman Ren SmallVector<Value *, 4> Ops(3); 178327f0100d1c1aa738d13b45d70eab08d0d2030fbManman Ren Type *Int64 = IntegerType::get(Context, 64); 179327f0100d1c1aa738d13b45d70eab08d0d2030fbManman Ren Ops[0] = createString(Name); 180a5b314c27a585b979ac9c9da944aa3cec27d22a6Manman Ren Ops[1] = Parent; 181a5b314c27a585b979ac9c9da944aa3cec27d22a6Manman Ren Ops[2] = ConstantInt::get(Int64, Offset); 182327f0100d1c1aa738d13b45d70eab08d0d2030fbManman Ren return MDNode::get(Context, Ops); 183327f0100d1c1aa738d13b45d70eab08d0d2030fbManman Ren } 184327f0100d1c1aa738d13b45d70eab08d0d2030fbManman Ren 185082bb7cf57e3a7089b8302a7d676fddf0bce276eManman Ren /// \brief Return metadata for a TBAA tag node with the given 186082bb7cf57e3a7089b8302a7d676fddf0bce276eManman Ren /// base type, access type and offset relative to the base type. 187082bb7cf57e3a7089b8302a7d676fddf0bce276eManman Ren MDNode *createTBAAStructTagNode(MDNode *BaseType, MDNode *AccessType, 188082bb7cf57e3a7089b8302a7d676fddf0bce276eManman Ren uint64_t Offset) { 189082bb7cf57e3a7089b8302a7d676fddf0bce276eManman Ren Type *Int64 = IntegerType::get(Context, 64); 190082bb7cf57e3a7089b8302a7d676fddf0bce276eManman Ren Value *Ops[3] = { BaseType, AccessType, ConstantInt::get(Int64, Offset) }; 191082bb7cf57e3a7089b8302a7d676fddf0bce276eManman Ren return MDNode::get(Context, Ops); 192082bb7cf57e3a7089b8302a7d676fddf0bce276eManman Ren } 193082bb7cf57e3a7089b8302a7d676fddf0bce276eManman Ren 194244b7a4ba66a8c23b6d0463eafc53b9a3970fc02Jakub Staszak}; 195e747fadedf8c5b80f1a0d5e84078a4428e06098eDuncan Sands 196e747fadedf8c5b80f1a0d5e84078a4428e06098eDuncan Sands} // end namespace llvm 197e747fadedf8c5b80f1a0d5e84078a4428e06098eDuncan Sands 198e747fadedf8c5b80f1a0d5e84078a4428e06098eDuncan Sands#endif 199