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