slang_rs_backend.cpp revision cecd11d2af5d45d8ba322bed61fb48a99c305528
1#include <vector> 2#include <string> 3 4#include "slang_rs_backend.hpp" 5#include "slang_rs_context.hpp" 6#include "slang_rs_export_var.hpp" 7#include "slang_rs_export_func.hpp" 8#include "slang_rs_export_type.hpp" 9 10#include "llvm/Metadata.h" /* for class llvm::NamedMDNode */ 11#include "llvm/ADT/Twine.h" /* for class llvm::Twine */ 12 13#include "clang/AST/DeclGroup.h" /* for class clang::DeclGroup */ 14#include "llvm/ADT/StringExtras.h" /* for function llvm::utostr_32() and llvm::itostr() */ 15 16#include "llvm/Support/IRBuilder.h" /* for class llvm::IRBuilder */ 17#include "llvm/Constant.h" /* for class llvm::Constant */ 18#include "llvm/Constants.h" /* for class llvm::Constant* */ 19#include "llvm/Module.h" /* for class llvm::Module */ 20#include "llvm/Function.h" /* for class llvm::Function */ 21#include "llvm/DerivedTypes.h" /* for class llvm::*Type */ 22 23#define MAKE 24 25namespace slang { 26 27RSBackend::RSBackend(RSContext* Context, 28 Diagnostic &Diags, 29 const CodeGenOptions& CodeGenOpts, 30 const TargetOptions& TargetOpts, 31 const PragmaList& Pragmas, 32 llvm::raw_ostream* OS, 33 SlangCompilerOutputTy OutputType, 34 SourceManager& SourceMgr, 35 bool AllowRSPrefix) : 36 Backend(Diags, 37 CodeGenOpts, 38 TargetOpts, 39 Pragmas, 40 OS, 41 OutputType, 42 SourceMgr, 43 AllowRSPrefix), 44 mContext(Context), 45 mExportVarMetadata(NULL), 46 mExportFuncMetadata(NULL), 47 mExportTypeMetadata(NULL) 48{ 49 return; 50} 51 52void RSBackend::HandleTopLevelDecl(DeclGroupRef D) { 53 Backend::HandleTopLevelDecl(D); 54 return; 55} 56 57void RSBackend::HandleTranslationUnitEx(ASTContext& Ctx) { 58 assert((&Ctx == mContext->getASTContext()) && "Unexpected AST context change during LLVM IR generation"); 59 mContext->processExport(); 60 61 /* Dump export variable info */ 62 if(mContext->hasExportVar()) { 63 if(mExportVarMetadata == NULL) 64 mExportVarMetadata = mpModule->getOrInsertNamedMetadata("#rs_export_var"); 65 66 llvm::SmallVector<llvm::Value*, 2> ExportVarInfo; 67 68 for(RSContext::const_export_var_iterator I = mContext->export_vars_begin(); 69 I != mContext->export_vars_end(); 70 I++) 71 { 72 const RSExportVar* EV = *I; 73 const RSExportType* ET = EV->getType(); 74 75 /* variable name */ 76 ExportVarInfo.push_back( llvm::MDString::get(mLLVMContext, EV->getName().c_str()) ); 77 78 /* type name */ 79 if(ET->getClass() == RSExportType::ExportClassPrimitive) 80 ExportVarInfo.push_back( llvm::MDString::get(mLLVMContext, llvm::utostr_32(static_cast<const RSExportPrimitiveType*>(ET)->getType())) ); 81 else if(ET->getClass() == RSExportType::ExportClassPointer) 82 ExportVarInfo.push_back( llvm::MDString::get(mLLVMContext, ("*" + static_cast<const RSExportPointerType*>(ET)->getPointeeType()->getName()).c_str()) ); 83 else 84 ExportVarInfo.push_back( llvm::MDString::get(mLLVMContext, EV->getType()->getName().c_str()) ); 85 86 mExportVarMetadata->addOperand( llvm::MDNode::get(mLLVMContext, ExportVarInfo.data(), ExportVarInfo.size()) ); 87 88 ExportVarInfo.clear(); 89 } 90 } 91 92 /* Dump export function info */ 93 if(mContext->hasExportFunc()) { 94 if(mExportFuncMetadata == NULL) 95 mExportFuncMetadata = mpModule->getOrInsertNamedMetadata("#rs_export_func"); 96 97 llvm::SmallVector<llvm::Value*, 1> ExportFuncInfo; 98 99 for(RSContext::const_export_func_iterator I = mContext->export_funcs_begin(); 100 I != mContext->export_funcs_end(); 101 I++) 102 { 103 const RSExportFunc* EF = *I; 104 105 /* function name */ 106 107 if(!EF->hasParam()) 108 ExportFuncInfo.push_back( llvm::MDString::get(mLLVMContext, EF->getName().c_str()) ); 109 else { 110 llvm::Function* F = mpModule->getFunction(EF->getName()); 111 llvm::Function* HelperFunction; 112 const std::string HelperFunctionName(".helper_" + EF->getName()); 113 114 assert(F && "Function marked as exported disappeared in Bitcode"); 115 116 /* Create helper function */ 117 { 118 llvm::PointerType* HelperFunctionParameterTypeP = llvm::PointerType::getUnqual(EF->getParamPacketType()->getLLVMType()); 119 llvm::FunctionType* HelperFunctionType; 120 std::vector<const llvm::Type*> Params; 121 122 Params.push_back(HelperFunctionParameterTypeP); 123 HelperFunctionType = llvm::FunctionType::get(F->getReturnType(), Params, false); 124 125 HelperFunction = llvm::Function::Create(HelperFunctionType, llvm::GlobalValue::ExternalLinkage, HelperFunctionName, mpModule); 126 127 HelperFunction->addFnAttr(llvm::Attribute::NoInline); 128 HelperFunction->setCallingConv(F->getCallingConv()); 129 130 /* Create helper function body */ 131 { 132 llvm::Argument* HelperFunctionParameter = &(*HelperFunction->arg_begin()); 133 llvm::BasicBlock* BB = llvm::BasicBlock::Create(mLLVMContext, "entry", HelperFunction); 134 llvm::IRBuilder<>* IB = new llvm::IRBuilder<>(BB); 135 llvm::SmallVector<llvm::Value*, 6> Params; 136 llvm::Value* Idx[2]; 137 138 Idx[0] = llvm::ConstantInt::get(llvm::Type::getInt32Ty(mLLVMContext), 0); 139 140 /* getelementptr and load instruction for all elements in parameter .p */ 141 int i; 142 for (i=0; i < EF->getNumParameters(); i++) { 143 144 /* getelementptr */ 145 Idx[1] = llvm::ConstantInt::get(llvm::Type::getInt32Ty(mLLVMContext), i); 146 llvm::Value* Ptr = IB->CreateInBoundsGEP(HelperFunctionParameter, Idx, Idx + 2); 147 148 /* load */ 149 llvm::Value* V = IB->CreateLoad(Ptr); 150 Params.push_back(V); 151 } 152 153 /* call and pass the all elements as paramter to F */ 154 llvm::CallInst* CI = IB->CreateCall(F, Params.data(), Params.data() + Params.size()); 155 CI->setCallingConv(F->getCallingConv()); 156 157 if(F->getReturnType() == llvm::Type::getVoidTy(mLLVMContext)) 158 IB->CreateRetVoid(); 159 else 160 IB->CreateRet(CI); 161 162 delete IB; 163 } 164 } 165 166 ExportFuncInfo.push_back( llvm::MDString::get(mLLVMContext, HelperFunctionName.c_str()) ); 167 } 168 169 mExportFuncMetadata->addOperand( llvm::MDNode::get(mLLVMContext, ExportFuncInfo.data(), ExportFuncInfo.size()) ); 170 171 ExportFuncInfo.clear(); 172 } 173 } 174 175 /* Dump export type info */ 176 if(mContext->hasExportType()) { 177 llvm::SmallVector<llvm::Value*, 1> ExportTypeInfo; 178 179 for(RSContext::const_export_type_iterator I = mContext->export_types_begin(); 180 I != mContext->export_types_end(); 181 I++) 182 { 183 /* First, dump type name list to export */ 184 const RSExportType* ET = I->getValue(); 185 186 ExportTypeInfo.clear(); 187 /* type name */ 188 ExportTypeInfo.push_back( llvm::MDString::get(mLLVMContext, ET->getName().c_str()) ); 189 190 if(ET->getClass() == RSExportType::ExportClassRecord) { 191 const RSExportRecordType* ERT = static_cast<const RSExportRecordType*>(ET); 192 193 if(mExportTypeMetadata == NULL) 194 mExportTypeMetadata = mpModule->getOrInsertNamedMetadata("#rs_export_type"); 195 196 mExportTypeMetadata->addOperand( llvm::MDNode::get(mLLVMContext, ExportTypeInfo.data(), ExportTypeInfo.size()) ); 197 198 /* Now, export struct field information to %[struct name] */ 199 std::string StructInfoMetadataName("%"); 200 StructInfoMetadataName.append(ET->getName()); 201 llvm::NamedMDNode* StructInfoMetadata = mpModule->getOrInsertNamedMetadata(StructInfoMetadataName); 202 llvm::SmallVector<llvm::Value*, 3> FieldInfo; 203 204 assert(StructInfoMetadata->getNumOperands() == 0 && "Metadata with same name was created before"); 205 for(RSExportRecordType::const_field_iterator FI = ERT->fields_begin(); 206 FI != ERT->fields_end(); 207 FI++) 208 { 209 const RSExportRecordType::Field* F = *FI; 210 211 /* 1. field name */ 212 FieldInfo.push_back( llvm::MDString::get(mLLVMContext, F->getName().c_str()) ); 213 /* 2. field type name */ 214 FieldInfo.push_back( llvm::MDString::get(mLLVMContext, F->getType()->getName().c_str()) ); 215 216 /* 3. field kind */ 217 switch(F->getType()->getClass()) { 218 case RSExportType::ExportClassPrimitive: 219 case RSExportType::ExportClassVector: 220 { 221 const RSExportPrimitiveType* EPT = static_cast<const RSExportPrimitiveType*>(F->getType()); 222 FieldInfo.push_back( llvm::MDString::get(mLLVMContext, llvm::itostr(EPT->getKind())) ); 223 } 224 break; 225 226 default: 227 FieldInfo.push_back( llvm::MDString::get(mLLVMContext, llvm::itostr(RSExportPrimitiveType::DataKindUser)) ); 228 break; 229 } 230 231 StructInfoMetadata->addOperand( llvm::MDNode::get(mLLVMContext, FieldInfo.data(), FieldInfo.size()) ); 232 233 FieldInfo.clear(); 234 } 235 } /* ET->getClass() == RSExportType::ExportClassRecord */ 236 } 237 } 238 239 return; 240} 241 242RSBackend::~RSBackend() { 243 return; 244} 245 246} /* namespace slang */ 247