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