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