blob: 450a68669b8d796de8a8d51a42582d0fb372afa8 [file] [log] [blame]
zonr6315f762010-10-05 15:35:14 +08001#include "slang_rs_backend.h"
2
3#include <vector>
4#include <string>
Shih-wei Liao462aefd2010-06-04 15:32:04 -07005
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07006#include "llvm/Metadata.h"
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07007#include "llvm/Constant.h"
8#include "llvm/Constants.h"
9#include "llvm/Module.h"
10#include "llvm/Function.h"
11#include "llvm/DerivedTypes.h"
Shih-wei Liao462aefd2010-06-04 15:32:04 -070012
zonr6315f762010-10-05 15:35:14 +080013#include "llvm/Support/IRBuilder.h"
14
15#include "llvm/ADT/Twine.h"
16#include "llvm/ADT/StringExtras.h"
17
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070018#include "clang/AST/DeclGroup.h"
Shih-wei Liao462aefd2010-06-04 15:32:04 -070019
zonr6315f762010-10-05 15:35:14 +080020#include "slang_rs_context.h"
21#include "slang_rs_export_var.h"
22#include "slang_rs_export_func.h"
23#include "slang_rs_export_type.h"
Shih-wei Liao462aefd2010-06-04 15:32:04 -070024
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070025using namespace slang;
26
27RSBackend::RSBackend(RSContext *Context,
28 clang::Diagnostic &Diags,
29 const clang::CodeGenOptions &CodeGenOpts,
30 const clang::TargetOptions &TargetOpts,
31 const PragmaList &Pragmas,
32 llvm::raw_ostream *OS,
Kirk Stewart6b226742010-06-11 10:51:12 -070033 SlangCompilerOutputTy OutputType,
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070034 clang::SourceManager &SourceMgr,
zonr6315f762010-10-05 15:35:14 +080035 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) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070048 return;
Shih-wei Liao462aefd2010-06-04 15:32:04 -070049}
50
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070051void RSBackend::HandleTopLevelDecl(clang::DeclGroupRef D) {
52 Backend::HandleTopLevelDecl(D);
53 return;
Shih-wei Liao462aefd2010-06-04 15:32:04 -070054}
55
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070056void RSBackend::HandleTranslationUnitEx(clang::ASTContext &Ctx) {
57 assert((&Ctx == mContext->getASTContext()) && "Unexpected AST context change"
58 " during LLVM IR generation");
59 mContext->processExport();
Shih-wei Liao462aefd2010-06-04 15:32:04 -070060
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070061 // Dump export variable info
62 if (mContext->hasExportVar()) {
63 if (mExportVarMetadata == NULL)
64 mExportVarMetadata = mpModule->getOrInsertNamedMetadata("#rs_export_var");
Shih-wei Liao462aefd2010-06-04 15:32:04 -070065
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070066 llvm::SmallVector<llvm::Value*, 2> ExportVarInfo;
Shih-wei Liao462aefd2010-06-04 15:32:04 -070067
zonr6315f762010-10-05 15:35:14 +080068 for (RSContext::const_export_var_iterator I = mContext->export_vars_begin(),
69 E = mContext->export_vars_end();
70 I != E;
71 I++) {
72 const RSExportVar *EV = *I;
73 const RSExportType *ET = EV->getType();
Shih-wei Liao462aefd2010-06-04 15:32:04 -070074
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070075 // Variable name
76 ExportVarInfo.push_back(
77 llvm::MDString::get(mLLVMContext, EV->getName().c_str()));
Shih-wei Liao462aefd2010-06-04 15:32:04 -070078
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070079 // Type name
80 if (ET->getClass() == RSExportType::ExportClassPrimitive)
81 ExportVarInfo.push_back(
82 llvm::MDString::get(
83 mLLVMContext, llvm::utostr_32(
zonr6315f762010-10-05 15:35:14 +080084 static_cast<const RSExportPrimitiveType*>(ET)->getType())));
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070085 else if (ET->getClass() == RSExportType::ExportClassPointer)
86 ExportVarInfo.push_back(
87 llvm::MDString::get(
88 mLLVMContext, ("*" + static_cast<const RSExportPointerType*>(ET)
zonr6315f762010-10-05 15:35:14 +080089 ->getPointeeType()->getName()).c_str()));
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070090 else
91 ExportVarInfo.push_back(
92 llvm::MDString::get(mLLVMContext,
93 EV->getType()->getName().c_str()));
Shih-wei Liao462aefd2010-06-04 15:32:04 -070094
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070095 mExportVarMetadata->addOperand(
96 llvm::MDNode::get(mLLVMContext,
97 ExportVarInfo.data(),
98 ExportVarInfo.size()) );
Shih-wei Liao462aefd2010-06-04 15:32:04 -070099
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700100 ExportVarInfo.clear();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700101 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700102 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700103
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700104 // Dump export function info
105 if (mContext->hasExportFunc()) {
106 if (mExportFuncMetadata == NULL)
107 mExportFuncMetadata =
108 mpModule->getOrInsertNamedMetadata("#rs_export_func");
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700109
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700110 llvm::SmallVector<llvm::Value*, 1> ExportFuncInfo;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700111
zonr6315f762010-10-05 15:35:14 +0800112 for (RSContext::const_export_func_iterator
113 I = mContext->export_funcs_begin(),
114 E = mContext->export_funcs_end();
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700115 I != E;
116 I++) {
zonr6315f762010-10-05 15:35:14 +0800117 const RSExportFunc *EF = *I;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700118
119 // Function name
zonr6315f762010-10-05 15:35:14 +0800120 if (!EF->hasParam()) {
121 ExportFuncInfo.push_back(llvm::MDString::get(mLLVMContext,
122 EF->getName().c_str()));
123 } else {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700124 llvm::Function *F = mpModule->getFunction(EF->getName());
125 llvm::Function *HelperFunction;
126 const std::string HelperFunctionName(".helper_" + EF->getName());
127
128 assert(F && "Function marked as exported disappeared in Bitcode");
129
130 // Create helper function
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700131 {
Zonr Chang0da0a7d2010-10-05 21:26:37 +0800132 llvm::StructType *HelperFunctionParameterTy = NULL;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700133
Zonr Chang0da0a7d2010-10-05 21:26:37 +0800134 if (!F->getArgumentList().empty()) {
135 std::vector<const llvm::Type*> HelperFunctionParameterTys;
136 for (llvm::Function::arg_iterator AI = F->arg_begin(),
137 AE = F->arg_end(); AI != AE; AI++)
138 HelperFunctionParameterTys.push_back(AI->getType());
139
140 HelperFunctionParameterTy =
141 llvm::StructType::get(mLLVMContext, HelperFunctionParameterTys);
142 }
143
144 if (!EF->checkParameterPacketType(HelperFunctionParameterTy)) {
145 fprintf(stderr, "Failed to export function %s: parameter type "
146 "mismatch during creation of helper function.\n",
147 EF->getName().c_str());
148
149 const RSExportRecordType *Expected = EF->getParamPacketType();
150 if (Expected) {
151 fprintf(stderr, "Expected:\n");
152 Expected->getLLVMType()->dump();
153 }
154 if (HelperFunctionParameterTy) {
155 fprintf(stderr, "Got:\n");
156 HelperFunctionParameterTy->dump();
157 }
158 }
159
160 std::vector<const llvm::Type*> Params;
161 if (HelperFunctionParameterTy) {
162 llvm::PointerType *HelperFunctionParameterTyP =
163 llvm::PointerType::getUnqual(HelperFunctionParameterTy);
164 Params.push_back(HelperFunctionParameterTyP);
165 }
166
167 llvm::FunctionType * HelperFunctionType =
168 llvm::FunctionType::get(F->getReturnType(),
169 Params,
170 /* IsVarArgs = */false);
Shih-wei Liaocecd11d2010-09-21 08:07:58 -0700171
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700172 HelperFunction =
173 llvm::Function::Create(HelperFunctionType,
174 llvm::GlobalValue::ExternalLinkage,
175 HelperFunctionName,
176 mpModule);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700177
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700178 HelperFunction->addFnAttr(llvm::Attribute::NoInline);
179 HelperFunction->setCallingConv(F->getCallingConv());
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700180
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700181 // Create helper function body
182 {
183 llvm::Argument *HelperFunctionParameter =
184 &(*HelperFunction->arg_begin());
185 llvm::BasicBlock *BB =
186 llvm::BasicBlock::Create(mLLVMContext, "entry", HelperFunction);
187 llvm::IRBuilder<> *IB = new llvm::IRBuilder<>(BB);
188 llvm::SmallVector<llvm::Value*, 6> Params;
189 llvm::Value *Idx[2];
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700190
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700191 Idx[0] =
192 llvm::ConstantInt::get(llvm::Type::getInt32Ty(mLLVMContext), 0);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700193
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700194 // getelementptr and load instruction for all elements in
195 // parameter .p
Zonr Chang0da0a7d2010-10-05 21:26:37 +0800196 for (size_t i = 0; i < EF->getNumParameters(); i++) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700197 // getelementptr
198 Idx[1] =
199 llvm::ConstantInt::get(
200 llvm::Type::getInt32Ty(mLLVMContext), i);
201 llvm::Value *Ptr = IB->CreateInBoundsGEP(HelperFunctionParameter,
202 Idx,
203 Idx + 2);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700204
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700205 // load
206 llvm::Value *V = IB->CreateLoad(Ptr);
207 Params.push_back(V);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700208 }
209
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700210 // Call and pass the all elements as paramter to F
211 llvm::CallInst *CI = IB->CreateCall(F,
212 Params.data(),
213 Params.data() + Params.size());
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700214
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700215 CI->setCallingConv(F->getCallingConv());
216
217 if (F->getReturnType() == llvm::Type::getVoidTy(mLLVMContext))
218 IB->CreateRetVoid();
219 else
220 IB->CreateRet(CI);
221
222 delete IB;
223 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700224 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700225
226 ExportFuncInfo.push_back(
227 llvm::MDString::get(mLLVMContext, HelperFunctionName.c_str()));
228 }
229
230 mExportFuncMetadata->addOperand(
231 llvm::MDNode::get(mLLVMContext,
232 ExportFuncInfo.data(),
233 ExportFuncInfo.size()));
234
235 ExportFuncInfo.clear();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700236 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700237 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700238
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700239 // Dump export type info
240 if (mContext->hasExportType()) {
241 llvm::SmallVector<llvm::Value*, 1> ExportTypeInfo;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700242
zonr6315f762010-10-05 15:35:14 +0800243 for (RSContext::const_export_type_iterator
244 I = mContext->export_types_begin(),
245 E = mContext->export_types_end();
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700246 I != E;
247 I++) {
248 // First, dump type name list to export
249 const RSExportType *ET = I->getValue();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700250
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700251 ExportTypeInfo.clear();
252 // Type name
253 ExportTypeInfo.push_back(
254 llvm::MDString::get(mLLVMContext, ET->getName().c_str()));
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700255
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700256 if (ET->getClass() == RSExportType::ExportClassRecord) {
257 const RSExportRecordType *ERT =
258 static_cast<const RSExportRecordType*>(ET);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700259
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700260 if (mExportTypeMetadata == NULL)
261 mExportTypeMetadata =
262 mpModule->getOrInsertNamedMetadata("#rs_export_type");
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700263
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700264 mExportTypeMetadata->addOperand(
265 llvm::MDNode::get(mLLVMContext,
266 ExportTypeInfo.data(),
267 ExportTypeInfo.size()));
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700268
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700269 // Now, export struct field information to %[struct name]
270 std::string StructInfoMetadataName("%");
271 StructInfoMetadataName.append(ET->getName());
272 llvm::NamedMDNode *StructInfoMetadata =
273 mpModule->getOrInsertNamedMetadata(StructInfoMetadataName);
274 llvm::SmallVector<llvm::Value*, 3> FieldInfo;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700275
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700276 assert(StructInfoMetadata->getNumOperands() == 0 &&
277 "Metadata with same name was created before");
zonr6315f762010-10-05 15:35:14 +0800278 for (RSExportRecordType::const_field_iterator FI = ERT->fields_begin(),
279 FE = ERT->fields_end();
280 FI != FE;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700281 FI++) {
282 const RSExportRecordType::Field *F = *FI;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700283
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700284 // 1. field name
285 FieldInfo.push_back(llvm::MDString::get(mLLVMContext,
286 F->getName().c_str()));
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700287
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700288 // 2. field type name
289 FieldInfo.push_back(
290 llvm::MDString::get(mLLVMContext,
291 F->getType()->getName().c_str()));
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700292
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700293 // 3. field kind
294 switch (F->getType()->getClass()) {
295 case RSExportType::ExportClassPrimitive:
296 case RSExportType::ExportClassVector: {
297 const RSExportPrimitiveType *EPT =
298 static_cast<const RSExportPrimitiveType*>(F->getType());
299 FieldInfo.push_back(
300 llvm::MDString::get(mLLVMContext,
301 llvm::itostr(EPT->getKind())));
302 break;
303 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700304
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700305 default: {
306 FieldInfo.push_back(
307 llvm::MDString::get(mLLVMContext,
308 llvm::itostr(
zonr6315f762010-10-05 15:35:14 +0800309 RSExportPrimitiveType::DataKindUser)));
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700310 break;
311 }
312 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700313
zonr6315f762010-10-05 15:35:14 +0800314 StructInfoMetadata->addOperand(llvm::MDNode::get(mLLVMContext,
315 FieldInfo.data(),
316 FieldInfo.size()));
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700317
318 FieldInfo.clear();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700319 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700320 } // ET->getClass() == RSExportType::ExportClassRecord
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700321 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700322 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700323
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700324 return;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700325}
326
327RSBackend::~RSBackend() {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700328 return;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700329}