slang_rs_backend.cpp revision 4c9f742efa36b1037acc640184681d421aa0f6ba
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 mContext(Context), 37 Backend(Diags, 38 CodeGenOpts, 39 TargetOpts, 40 Pragmas, 41 OS, 42 OutputType, 43 SourceMgr, 44 AllowRSPrefix), 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 = llvm::NamedMDNode::Create(mLLVMContext, "#rs_export_var", NULL, 0, mpModule); 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 = llvm::NamedMDNode::Create(mLLVMContext, "#rs_export_func", NULL, 0, mpModule); 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 if(!EF->hasParam()) 107 ExportFuncInfo.push_back( llvm::MDString::get(mLLVMContext, EF->getName().c_str()) ); 108 else { 109 llvm::Function* F = mpModule->getFunction(EF->getName()); 110 llvm::Function* HelperFunction; 111 const std::string HelperFunctionName(".helper_" + EF->getName()); 112 113 assert(F && "Function marked as exported disappeared in Bitcode"); 114 115 /* Create helper function */ 116 { 117 llvm::PointerType* HelperFunctionParameterTypeP = llvm::PointerType::getUnqual(EF->getParamPacketType()->getLLVMType()); 118 llvm::FunctionType* HelperFunctionType; 119 std::vector<const llvm::Type*> Params; 120 121 Params.push_back(HelperFunctionParameterTypeP); 122 HelperFunctionType = llvm::FunctionType::get(F->getReturnType(), Params, false); 123 124 HelperFunction = llvm::Function::Create(HelperFunctionType, llvm::GlobalValue::ExternalLinkage, HelperFunctionName, mpModule); 125 126 HelperFunction->addFnAttr(llvm::Attribute::NoInline); 127 HelperFunction->setCallingConv(F->getCallingConv()); 128 129 /* Create helper function body */ 130 { 131 llvm::Argument* HelperFunctionParameter = &(*HelperFunction->arg_begin()); 132 llvm::BasicBlock* BB = llvm::BasicBlock::Create(mLLVMContext, "entry", HelperFunction); 133 llvm::IRBuilder<>* IB = new llvm::IRBuilder<>(BB); 134 llvm::SmallVector<llvm::Value*, 6> Params; 135 llvm::Value* Idx[2]; 136 137 Idx[0] = llvm::ConstantInt::get(llvm::Type::getInt32Ty(mLLVMContext), 0); 138 139 /* getelementptr and load instruction for all elements in parameter .p */ 140 for(int i=0;i<EF->getNumParameters();i++) { 141 /* getelementptr */ 142 Idx[1] = llvm::ConstantInt::get(llvm::Type::getInt32Ty(mLLVMContext), i); 143 llvm::Value* Ptr = IB->CreateInBoundsGEP(HelperFunctionParameter, Idx, Idx + 2); 144 /* load */ 145 llvm::Value* V = IB->CreateLoad(Ptr); 146 Params.push_back(V); 147 } 148 149 /* call and pass the all elements as paramter to F */ 150 llvm::CallInst* CI = IB->CreateCall(F, Params.data(), Params.data() + Params.size()); 151 CI->setCallingConv(F->getCallingConv()); 152 153 if(F->getReturnType() == llvm::Type::getVoidTy(mLLVMContext)) 154 IB->CreateRetVoid(); 155 else 156 IB->CreateRet(CI); 157 158 delete IB; 159 } 160 } 161 162 ExportFuncInfo.push_back( llvm::MDString::get(mLLVMContext, HelperFunctionName.c_str()) ); 163 } 164 165 mExportFuncMetadata->addOperand( llvm::MDNode::get(mLLVMContext, ExportFuncInfo.data(), ExportFuncInfo.size()) ); 166 167 ExportFuncInfo.clear(); 168 } 169 } 170 171 /* Dump export type info */ 172 if(mContext->hasExportType()) { 173 llvm::SmallVector<llvm::Value*, 1> ExportTypeInfo; 174 175 for(RSContext::const_export_type_iterator I = mContext->export_types_begin(); 176 I != mContext->export_types_end(); 177 I++) 178 { 179 /* First, dump type name list to export */ 180 const RSExportType* ET = I->getValue(); 181 182 ExportTypeInfo.clear(); 183 /* type name */ 184 ExportTypeInfo.push_back( llvm::MDString::get(mLLVMContext, ET->getName().c_str()) ); 185 186 if(ET->getClass() == RSExportType::ExportClassRecord) { 187 const RSExportRecordType* ERT = static_cast<const RSExportRecordType*>(ET); 188 189 if(mExportTypeMetadata == NULL) 190 mExportTypeMetadata = llvm::NamedMDNode::Create(mLLVMContext, "#rs_export_type", NULL, 0, mpModule); 191 192 mExportTypeMetadata->addOperand( llvm::MDNode::get(mLLVMContext, ExportTypeInfo.data(), ExportTypeInfo.size()) ); 193 194 /* Now, export struct field information to %[struct name] */ 195 std::string StructInfoMetadataName("%"); 196 StructInfoMetadataName.append(ET->getName()); 197 llvm::NamedMDNode* StructInfoMetadata = llvm::NamedMDNode::Create(mLLVMContext, StructInfoMetadataName.c_str(), NULL, 0, mpModule); 198 llvm::SmallVector<llvm::Value*, 3> FieldInfo; 199 200 assert(StructInfoMetadata->getNumOperands() == 0 && "Metadata with same name was created before"); 201 for(RSExportRecordType::const_field_iterator FI = ERT->fields_begin(); 202 FI != ERT->fields_end(); 203 FI++) 204 { 205 const RSExportRecordType::Field* F = *FI; 206 207 /* 1. field name */ 208 FieldInfo.push_back( llvm::MDString::get(mLLVMContext, F->getName().c_str()) ); 209 /* 2. field type name */ 210 FieldInfo.push_back( llvm::MDString::get(mLLVMContext, F->getType()->getName().c_str()) ); 211 212 /* 3. field kind */ 213 switch(F->getType()->getClass()) { 214 case RSExportType::ExportClassPrimitive: 215 case RSExportType::ExportClassVector: 216 { 217 RSExportPrimitiveType* EPT = (RSExportPrimitiveType*) F->getType(); 218 FieldInfo.push_back( llvm::MDString::get(mLLVMContext, llvm::itostr(EPT->getKind())) ); 219 } 220 break; 221 222 default: 223 FieldInfo.push_back( llvm::MDString::get(mLLVMContext, llvm::itostr(RSExportPrimitiveType::DataKindUser)) ); 224 break; 225 } 226 227 StructInfoMetadata->addOperand( llvm::MDNode::get(mLLVMContext, FieldInfo.data(), FieldInfo.size()) ); 228 229 FieldInfo.clear(); 230 } 231 } /* ET->getClass() == RSExportType::ExportClassRecord */ 232 } 233 } 234 235 return; 236} 237 238RSBackend::~RSBackend() { 239 return; 240} 241 242} /* namespace slang */ 243