blob: 0a53d11b825f28cb429b382f9e7c2eb4967da423 [file] [log] [blame]
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001#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,
Kirk Stewart6b226742010-06-11 10:51:12 -070033 SlangCompilerOutputTy OutputType,
Kirk Stewart1fd85792010-07-07 09:51:23 -070034 SourceManager& SourceMgr,
35 bool AllowRSPrefix) :
Shih-wei Liao462aefd2010-06-04 15:32:04 -070036 Backend(Diags,
37 CodeGenOpts,
38 TargetOpts,
39 Pragmas,
40 OS,
Kirk Stewart6b226742010-06-11 10:51:12 -070041 OutputType,
Kirk Stewart1fd85792010-07-07 09:51:23 -070042 SourceMgr,
43 AllowRSPrefix),
Shih-wei Liaocecd11d2010-09-21 08:07:58 -070044 mContext(Context),
Shih-wei Liao4c9f7422010-08-05 04:30:02 -070045 mExportVarMetadata(NULL),
46 mExportFuncMetadata(NULL),
47 mExportTypeMetadata(NULL)
Shih-wei Liao462aefd2010-06-04 15:32:04 -070048{
49 return;
50}
51
52void RSBackend::HandleTopLevelDecl(DeclGroupRef D) {
53 Backend::HandleTopLevelDecl(D);
54 return;
55}
56
57void RSBackend::HandleTranslationUnitEx(ASTContext& Ctx) {
Shih-wei Liao001fb6d2010-06-21 11:17:11 -070058 assert((&Ctx == mContext->getASTContext()) && "Unexpected AST context change during LLVM IR generation");
59 mContext->processExport();
Shih-wei Liao462aefd2010-06-04 15:32:04 -070060
61 /* Dump export variable info */
62 if(mContext->hasExportVar()) {
63 if(mExportVarMetadata == NULL)
Shih-wei Liaof52a6202010-09-10 17:40:53 -070064 mExportVarMetadata = mpModule->getOrInsertNamedMetadata("#rs_export_var");
Shih-wei Liao462aefd2010-06-04 15:32:04 -070065
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 */
Shih-wei Liao4c9f7422010-08-05 04:30:02 -070079 if(ET->getClass() == RSExportType::ExportClassPrimitive)
Shih-wei Liao462aefd2010-06-04 15:32:04 -070080 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)
Shih-wei Liaof52a6202010-09-10 17:40:53 -070095 mExportFuncMetadata = mpModule->getOrInsertNamedMetadata("#rs_export_func");
Shih-wei Liao462aefd2010-06-04 15:32:04 -070096
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 */
Shih-wei Liaocecd11d2010-09-21 08:07:58 -0700106
Shih-wei Liao4c9f7422010-08-05 04:30:02 -0700107 if(!EF->hasParam())
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700108 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;
Shih-wei Liao4c9f7422010-08-05 04:30:02 -0700112 const std::string HelperFunctionName(".helper_" + EF->getName());
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700113
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 */
Shih-wei Liao1ebc0ca2010-09-14 10:57:21 -0700141 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);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700151 }
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)
Shih-wei Liaof52a6202010-09-10 17:40:53 -0700194 mExportTypeMetadata = mpModule->getOrInsertNamedMetadata("#rs_export_type");
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700195
196 mExportTypeMetadata->addOperand( llvm::MDNode::get(mLLVMContext, ExportTypeInfo.data(), ExportTypeInfo.size()) );
197
198 /* Now, export struct field information to %[struct name] */
Shih-wei Liao4c9f7422010-08-05 04:30:02 -0700199 std::string StructInfoMetadataName("%");
200 StructInfoMetadataName.append(ET->getName());
Shih-wei Liaof52a6202010-09-10 17:40:53 -0700201 llvm::NamedMDNode* StructInfoMetadata = mpModule->getOrInsertNamedMetadata(StructInfoMetadataName);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700202 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 {
Shih-wei Liaocecd11d2010-09-21 08:07:58 -0700221 const RSExportPrimitiveType* EPT = static_cast<const RSExportPrimitiveType*>(F->getType());
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700222 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 */