blob: ea138cc6c1ec584cd7e97eee99e6743389344b0f [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 {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700132 llvm::PointerType *HelperFunctionParameterTypeP =
133 llvm::PointerType::getUnqual(
134 EF->getParamPacketType()->getLLVMType());
135 llvm::FunctionType *HelperFunctionType;
136 std::vector<const llvm::Type*> Params;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700137
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700138 Params.push_back(HelperFunctionParameterTypeP);
139 HelperFunctionType = llvm::FunctionType::get(F->getReturnType(),
140 Params,
141 false);
Shih-wei Liaocecd11d2010-09-21 08:07:58 -0700142
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700143 HelperFunction =
144 llvm::Function::Create(HelperFunctionType,
145 llvm::GlobalValue::ExternalLinkage,
146 HelperFunctionName,
147 mpModule);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700148
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700149 HelperFunction->addFnAttr(llvm::Attribute::NoInline);
150 HelperFunction->setCallingConv(F->getCallingConv());
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700151
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700152 // Create helper function body
153 {
154 llvm::Argument *HelperFunctionParameter =
155 &(*HelperFunction->arg_begin());
156 llvm::BasicBlock *BB =
157 llvm::BasicBlock::Create(mLLVMContext, "entry", HelperFunction);
158 llvm::IRBuilder<> *IB = new llvm::IRBuilder<>(BB);
159 llvm::SmallVector<llvm::Value*, 6> Params;
160 llvm::Value *Idx[2];
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700161
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700162 Idx[0] =
163 llvm::ConstantInt::get(llvm::Type::getInt32Ty(mLLVMContext), 0);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700164
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700165 // getelementptr and load instruction for all elements in
166 // parameter .p
167 for (int i = 0; i < EF->getNumParameters(); i++) {
168 // getelementptr
169 Idx[1] =
170 llvm::ConstantInt::get(
171 llvm::Type::getInt32Ty(mLLVMContext), i);
172 llvm::Value *Ptr = IB->CreateInBoundsGEP(HelperFunctionParameter,
173 Idx,
174 Idx + 2);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700175
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700176 // load
177 llvm::Value *V = IB->CreateLoad(Ptr);
178 Params.push_back(V);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700179 }
180
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700181 // Call and pass the all elements as paramter to F
182 llvm::CallInst *CI = IB->CreateCall(F,
183 Params.data(),
184 Params.data() + Params.size());
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700185
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700186 CI->setCallingConv(F->getCallingConv());
187
188 if (F->getReturnType() == llvm::Type::getVoidTy(mLLVMContext))
189 IB->CreateRetVoid();
190 else
191 IB->CreateRet(CI);
192
193 delete IB;
194 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700195 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700196
197 ExportFuncInfo.push_back(
198 llvm::MDString::get(mLLVMContext, HelperFunctionName.c_str()));
199 }
200
201 mExportFuncMetadata->addOperand(
202 llvm::MDNode::get(mLLVMContext,
203 ExportFuncInfo.data(),
204 ExportFuncInfo.size()));
205
206 ExportFuncInfo.clear();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700207 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700208 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700209
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700210 // Dump export type info
211 if (mContext->hasExportType()) {
212 llvm::SmallVector<llvm::Value*, 1> ExportTypeInfo;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700213
zonr6315f762010-10-05 15:35:14 +0800214 for (RSContext::const_export_type_iterator
215 I = mContext->export_types_begin(),
216 E = mContext->export_types_end();
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700217 I != E;
218 I++) {
219 // First, dump type name list to export
220 const RSExportType *ET = I->getValue();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700221
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700222 ExportTypeInfo.clear();
223 // Type name
224 ExportTypeInfo.push_back(
225 llvm::MDString::get(mLLVMContext, ET->getName().c_str()));
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700226
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700227 if (ET->getClass() == RSExportType::ExportClassRecord) {
228 const RSExportRecordType *ERT =
229 static_cast<const RSExportRecordType*>(ET);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700230
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700231 if (mExportTypeMetadata == NULL)
232 mExportTypeMetadata =
233 mpModule->getOrInsertNamedMetadata("#rs_export_type");
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700234
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700235 mExportTypeMetadata->addOperand(
236 llvm::MDNode::get(mLLVMContext,
237 ExportTypeInfo.data(),
238 ExportTypeInfo.size()));
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700239
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700240 // Now, export struct field information to %[struct name]
241 std::string StructInfoMetadataName("%");
242 StructInfoMetadataName.append(ET->getName());
243 llvm::NamedMDNode *StructInfoMetadata =
244 mpModule->getOrInsertNamedMetadata(StructInfoMetadataName);
245 llvm::SmallVector<llvm::Value*, 3> FieldInfo;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700246
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700247 assert(StructInfoMetadata->getNumOperands() == 0 &&
248 "Metadata with same name was created before");
zonr6315f762010-10-05 15:35:14 +0800249 for (RSExportRecordType::const_field_iterator FI = ERT->fields_begin(),
250 FE = ERT->fields_end();
251 FI != FE;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700252 FI++) {
253 const RSExportRecordType::Field *F = *FI;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700254
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700255 // 1. field name
256 FieldInfo.push_back(llvm::MDString::get(mLLVMContext,
257 F->getName().c_str()));
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700258
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700259 // 2. field type name
260 FieldInfo.push_back(
261 llvm::MDString::get(mLLVMContext,
262 F->getType()->getName().c_str()));
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700263
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700264 // 3. field kind
265 switch (F->getType()->getClass()) {
266 case RSExportType::ExportClassPrimitive:
267 case RSExportType::ExportClassVector: {
268 const RSExportPrimitiveType *EPT =
269 static_cast<const RSExportPrimitiveType*>(F->getType());
270 FieldInfo.push_back(
271 llvm::MDString::get(mLLVMContext,
272 llvm::itostr(EPT->getKind())));
273 break;
274 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700275
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700276 default: {
277 FieldInfo.push_back(
278 llvm::MDString::get(mLLVMContext,
279 llvm::itostr(
zonr6315f762010-10-05 15:35:14 +0800280 RSExportPrimitiveType::DataKindUser)));
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700281 break;
282 }
283 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700284
zonr6315f762010-10-05 15:35:14 +0800285 StructInfoMetadata->addOperand(llvm::MDNode::get(mLLVMContext,
286 FieldInfo.data(),
287 FieldInfo.size()));
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700288
289 FieldInfo.clear();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700290 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700291 } // ET->getClass() == RSExportType::ExportClassRecord
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700292 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700293 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700294
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700295 return;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700296}
297
298RSBackend::~RSBackend() {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700299 return;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700300}