blob: ee73c381cd4ace054132dc7102d86b49b68e2689 [file] [log] [blame]
Chris Lattner31c2ec32007-05-06 20:31:17 +00001//===-- MSILWriter.cpp - Library for converting LLVM code to MSIL ---------===//
Anton Korobeynikov099883f2007-03-21 21:38:25 +00002//
Bill Wendling85db3a92008-02-26 10:57:23 +00003// The LLVM Compiler Infrastructure
Anton Korobeynikov099883f2007-03-21 21:38:25 +00004//
Chris Lattner4ee451d2007-12-29 20:36:04 +00005// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
Anton Korobeynikov099883f2007-03-21 21:38:25 +00007//
8//===----------------------------------------------------------------------===//
9//
10// This library converts LLVM code to MSIL code.
11//
12//===----------------------------------------------------------------------===//
13
14#include "MSILWriter.h"
15#include "llvm/CallingConv.h"
16#include "llvm/DerivedTypes.h"
17#include "llvm/Intrinsics.h"
18#include "llvm/IntrinsicInst.h"
19#include "llvm/TypeSymbolTable.h"
20#include "llvm/Analysis/ConstantsScanner.h"
21#include "llvm/Support/CallSite.h"
22#include "llvm/Support/InstVisitor.h"
Anton Korobeynikovf13090c2007-05-06 20:13:33 +000023#include "llvm/Support/MathExtras.h"
Anton Korobeynikov099883f2007-03-21 21:38:25 +000024#include "llvm/Transforms/Scalar.h"
25#include "llvm/ADT/StringExtras.h"
Gordon Henriksence224772008-01-07 01:30:38 +000026#include "llvm/CodeGen/Passes.h"
Anton Korobeynikov099883f2007-03-21 21:38:25 +000027
28namespace {
29 // TargetMachine for the MSIL
30 struct VISIBILITY_HIDDEN MSILTarget : public TargetMachine {
31 const TargetData DataLayout; // Calculates type size & alignment
32
33 MSILTarget(const Module &M, const std::string &FS)
34 : DataLayout(&M) {}
35
36 virtual bool WantsWholeFile() const { return true; }
Owen Andersoncb371882008-08-21 00:14:44 +000037 virtual bool addPassesToEmitWholeFile(PassManager &PM, raw_ostream &Out,
Bill Wendlingbe8cc2a2009-04-29 00:15:41 +000038 CodeGenFileType FileType,
Bill Wendling98a366d2009-04-29 23:29:43 +000039 CodeGenOpt::Level OptLevel);
Anton Korobeynikov099883f2007-03-21 21:38:25 +000040
41 // This class always works, but shouldn't be the default in most cases.
42 static unsigned getModuleMatchQuality(const Module &M) { return 1; }
43
44 virtual const TargetData *getTargetData() const { return &DataLayout; }
45 };
46}
47
Oscar Fuentes92adc192008-11-15 21:36:30 +000048/// MSILTargetMachineModule - Note that this is used on hosts that
49/// cannot link in a library unless there are references into the
50/// library. In particular, it seems that it is not possible to get
51/// things to work on Win32 without this. Though it is unused, do not
52/// remove it.
53extern "C" int MSILTargetMachineModule;
54int MSILTargetMachineModule = 0;
Anton Korobeynikov099883f2007-03-21 21:38:25 +000055
Dan Gohmanb8cab922008-10-14 20:25:08 +000056static RegisterTarget<MSILTarget> X("msil", "MSIL backend");
Anton Korobeynikov099883f2007-03-21 21:38:25 +000057
Bob Wilsona96751f2009-06-23 23:59:40 +000058// Force static initialization.
59extern "C" void LLVMInitializeMSILTarget() { }
Douglas Gregor1555a232009-06-16 20:12:29 +000060
Anton Korobeynikov099883f2007-03-21 21:38:25 +000061bool MSILModule::runOnModule(Module &M) {
62 ModulePtr = &M;
63 TD = &getAnalysis<TargetData>();
64 bool Changed = false;
65 // Find named types.
66 TypeSymbolTable& Table = M.getTypeSymbolTable();
67 std::set<const Type *> Types = getAnalysis<FindUsedTypes>().getTypes();
68 for (TypeSymbolTable::iterator I = Table.begin(), E = Table.end(); I!=E; ) {
69 if (!isa<StructType>(I->second) && !isa<OpaqueType>(I->second))
70 Table.remove(I++);
71 else {
72 std::set<const Type *>::iterator T = Types.find(I->second);
73 if (T==Types.end())
74 Table.remove(I++);
75 else {
76 Types.erase(T);
77 ++I;
78 }
79 }
80 }
81 // Find unnamed types.
82 unsigned RenameCounter = 0;
83 for (std::set<const Type *>::const_iterator I = Types.begin(),
84 E = Types.end(); I!=E; ++I)
85 if (const StructType *STy = dyn_cast<StructType>(*I)) {
86 while (ModulePtr->addTypeName("unnamed$"+utostr(RenameCounter), STy))
87 ++RenameCounter;
88 Changed = true;
89 }
90 // Pointer for FunctionPass.
91 UsedTypes = &getAnalysis<FindUsedTypes>().getTypes();
92 return Changed;
93}
94
Devang Patel19974732007-05-03 01:11:54 +000095char MSILModule::ID = 0;
96char MSILWriter::ID = 0;
Anton Korobeynikov099883f2007-03-21 21:38:25 +000097
98bool MSILWriter::runOnFunction(Function &F) {
99 if (F.isDeclaration()) return false;
Chris Lattner9062d9a2009-04-17 00:26:12 +0000100
101 // Do not codegen any 'available_externally' functions at all, they have
102 // definitions outside the translation unit.
103 if (F.hasAvailableExternallyLinkage())
104 return false;
105
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000106 LInfo = &getAnalysis<LoopInfo>();
107 printFunction(F);
108 return false;
109}
110
111
112bool MSILWriter::doInitialization(Module &M) {
113 ModulePtr = &M;
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000114 Mang = new Mangler(M);
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000115 Out << ".assembly extern mscorlib {}\n";
116 Out << ".assembly MSIL {}\n\n";
117 Out << "// External\n";
118 printExternals();
119 Out << "// Declarations\n";
120 printDeclarations(M.getTypeSymbolTable());
121 Out << "// Definitions\n";
122 printGlobalVariables();
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000123 Out << "// Startup code\n";
124 printModuleStartup();
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000125 return false;
126}
127
128
129bool MSILWriter::doFinalization(Module &M) {
130 delete Mang;
131 return false;
132}
133
134
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000135void MSILWriter::printModuleStartup() {
136 Out <<
137 ".method static public int32 $MSIL_Startup() {\n"
138 "\t.entrypoint\n"
139 "\t.locals (native int i)\n"
140 "\t.locals (native int argc)\n"
141 "\t.locals (native int ptr)\n"
142 "\t.locals (void* argv)\n"
143 "\t.locals (string[] args)\n"
144 "\tcall\tstring[] [mscorlib]System.Environment::GetCommandLineArgs()\n"
145 "\tdup\n"
146 "\tstloc\targs\n"
147 "\tldlen\n"
148 "\tconv.i4\n"
149 "\tdup\n"
150 "\tstloc\targc\n";
151 printPtrLoad(TD->getPointerSize());
152 Out <<
153 "\tmul\n"
154 "\tlocalloc\n"
155 "\tstloc\targv\n"
156 "\tldc.i4.0\n"
157 "\tstloc\ti\n"
158 "L_01:\n"
159 "\tldloc\ti\n"
160 "\tldloc\targc\n"
161 "\tceq\n"
162 "\tbrtrue\tL_02\n"
163 "\tldloc\targs\n"
164 "\tldloc\ti\n"
165 "\tldelem.ref\n"
166 "\tcall\tnative int [mscorlib]System.Runtime.InteropServices.Marshal::"
167 "StringToHGlobalAnsi(string)\n"
168 "\tstloc\tptr\n"
169 "\tldloc\targv\n"
170 "\tldloc\ti\n";
171 printPtrLoad(TD->getPointerSize());
172 Out <<
173 "\tmul\n"
174 "\tadd\n"
175 "\tldloc\tptr\n"
176 "\tstind.i\n"
177 "\tldloc\ti\n"
178 "\tldc.i4.1\n"
179 "\tadd\n"
180 "\tstloc\ti\n"
181 "\tbr\tL_01\n"
182 "L_02:\n"
183 "\tcall void $MSIL_Init()\n";
184
185 // Call user 'main' function.
186 const Function* F = ModulePtr->getFunction("main");
187 if (!F || F->isDeclaration()) {
188 Out << "\tldc.i4.0\n\tret\n}\n";
189 return;
190 }
Nick Lewycky9c0f1462009-03-19 05:51:39 +0000191 bool BadSig = true;
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000192 std::string Args("");
193 Function::const_arg_iterator Arg1,Arg2;
194
195 switch (F->arg_size()) {
196 case 0:
197 BadSig = false;
198 break;
199 case 1:
200 Arg1 = F->arg_begin();
201 if (Arg1->getType()->isInteger()) {
202 Out << "\tldloc\targc\n";
203 Args = getTypeName(Arg1->getType());
204 BadSig = false;
205 }
206 break;
207 case 2:
208 Arg1 = Arg2 = F->arg_begin(); ++Arg2;
209 if (Arg1->getType()->isInteger() &&
210 Arg2->getType()->getTypeID() == Type::PointerTyID) {
211 Out << "\tldloc\targc\n\tldloc\targv\n";
212 Args = getTypeName(Arg1->getType())+","+getTypeName(Arg2->getType());
213 BadSig = false;
214 }
215 break;
216 default:
217 BadSig = true;
218 }
219
220 bool RetVoid = (F->getReturnType()->getTypeID() == Type::VoidTyID);
Anton Korobeynikov7c1c2612008-02-20 11:22:39 +0000221 if (BadSig || (!F->getReturnType()->isInteger() && !RetVoid)) {
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000222 Out << "\tldc.i4.0\n";
223 } else {
224 Out << "\tcall\t" << getTypeName(F->getReturnType()) <<
225 getConvModopt(F->getCallingConv()) << "main(" << Args << ")\n";
226 if (RetVoid)
227 Out << "\tldc.i4.0\n";
228 else
229 Out << "\tconv.i4\n";
230 }
231 Out << "\tret\n}\n";
232}
233
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000234bool MSILWriter::isZeroValue(const Value* V) {
235 if (const Constant *C = dyn_cast<Constant>(V))
236 return C->isNullValue();
237 return false;
238}
239
240
241std::string MSILWriter::getValueName(const Value* V) {
242 // Name into the quotes allow control and space characters.
243 return "'"+Mang->getValueName(V)+"'";
244}
245
246
247std::string MSILWriter::getLabelName(const std::string& Name) {
248 if (Name.find('.')!=std::string::npos) {
249 std::string Tmp(Name);
250 // Replace unaccepable characters in the label name.
251 for (std::string::iterator I = Tmp.begin(), E = Tmp.end(); I!=E; ++I)
252 if (*I=='.') *I = '@';
253 return Tmp;
254 }
255 return Name;
256}
257
258
259std::string MSILWriter::getLabelName(const Value* V) {
260 return getLabelName(Mang->getValueName(V));
261}
262
263
264std::string MSILWriter::getConvModopt(unsigned CallingConvID) {
265 switch (CallingConvID) {
266 case CallingConv::C:
267 case CallingConv::Cold:
268 case CallingConv::Fast:
269 return "modopt([mscorlib]System.Runtime.CompilerServices.CallConvCdecl) ";
270 case CallingConv::X86_FastCall:
271 return "modopt([mscorlib]System.Runtime.CompilerServices.CallConvFastcall) ";
272 case CallingConv::X86_StdCall:
273 return "modopt([mscorlib]System.Runtime.CompilerServices.CallConvStdcall) ";
274 default:
275 cerr << "CallingConvID = " << CallingConvID << '\n';
276 assert(0 && "Unsupported calling convention");
277 }
Chris Lattnerd27c9912008-03-30 18:22:13 +0000278 return ""; // Not reached
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000279}
280
281
282std::string MSILWriter::getArrayTypeName(Type::TypeID TyID, const Type* Ty) {
283 std::string Tmp = "";
284 const Type* ElemTy = Ty;
285 assert(Ty->getTypeID()==TyID && "Invalid type passed");
286 // Walk trought array element types.
287 for (;;) {
288 // Multidimensional array.
289 if (ElemTy->getTypeID()==TyID) {
290 if (const ArrayType* ATy = dyn_cast<ArrayType>(ElemTy))
291 Tmp += utostr(ATy->getNumElements());
292 else if (const VectorType* VTy = dyn_cast<VectorType>(ElemTy))
293 Tmp += utostr(VTy->getNumElements());
294 ElemTy = cast<SequentialType>(ElemTy)->getElementType();
295 }
296 // Base element type found.
297 if (ElemTy->getTypeID()!=TyID) break;
298 Tmp += ",";
299 }
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000300 return getTypeName(ElemTy, false, true)+"["+Tmp+"]";
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000301}
302
303
304std::string MSILWriter::getPrimitiveTypeName(const Type* Ty, bool isSigned) {
305 unsigned NumBits = 0;
306 switch (Ty->getTypeID()) {
307 case Type::VoidTyID:
308 return "void ";
309 case Type::IntegerTyID:
310 NumBits = getBitWidth(Ty);
311 if(NumBits==1)
312 return "bool ";
313 if (!isSigned)
314 return "unsigned int"+utostr(NumBits)+" ";
315 return "int"+utostr(NumBits)+" ";
316 case Type::FloatTyID:
317 return "float32 ";
318 case Type::DoubleTyID:
319 return "float64 ";
320 default:
321 cerr << "Type = " << *Ty << '\n';
322 assert(0 && "Invalid primitive type");
323 }
Chris Lattnerd27c9912008-03-30 18:22:13 +0000324 return ""; // Not reached
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000325}
326
327
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000328std::string MSILWriter::getTypeName(const Type* Ty, bool isSigned,
329 bool isNested) {
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000330 if (Ty->isPrimitiveType() || Ty->isInteger())
331 return getPrimitiveTypeName(Ty,isSigned);
332 // FIXME: "OpaqueType" support
333 switch (Ty->getTypeID()) {
334 case Type::PointerTyID:
335 return "void* ";
336 case Type::StructTyID:
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000337 if (isNested)
338 return ModulePtr->getTypeName(Ty);
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000339 return "valuetype '"+ModulePtr->getTypeName(Ty)+"' ";
340 case Type::ArrayTyID:
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000341 if (isNested)
342 return getArrayTypeName(Ty->getTypeID(),Ty);
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000343 return "valuetype '"+getArrayTypeName(Ty->getTypeID(),Ty)+"' ";
344 case Type::VectorTyID:
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000345 if (isNested)
346 return getArrayTypeName(Ty->getTypeID(),Ty);
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000347 return "valuetype '"+getArrayTypeName(Ty->getTypeID(),Ty)+"' ";
348 default:
349 cerr << "Type = " << *Ty << '\n';
350 assert(0 && "Invalid type in getTypeName()");
351 }
Chris Lattnerd27c9912008-03-30 18:22:13 +0000352 return ""; // Not reached
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000353}
354
355
356MSILWriter::ValueType MSILWriter::getValueLocation(const Value* V) {
357 // Function argument
358 if (isa<Argument>(V))
359 return ArgumentVT;
360 // Function
361 else if (const Function* F = dyn_cast<Function>(V))
Rafael Espindolabb46f522009-01-15 20:18:42 +0000362 return F->hasLocalLinkage() ? InternalVT : GlobalVT;
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000363 // Variable
364 else if (const GlobalVariable* G = dyn_cast<GlobalVariable>(V))
Rafael Espindolabb46f522009-01-15 20:18:42 +0000365 return G->hasLocalLinkage() ? InternalVT : GlobalVT;
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000366 // Constant
367 else if (isa<Constant>(V))
368 return isa<ConstantExpr>(V) ? ConstExprVT : ConstVT;
369 // Local variable
370 return LocalVT;
371}
372
373
374std::string MSILWriter::getTypePostfix(const Type* Ty, bool Expand,
375 bool isSigned) {
376 unsigned NumBits = 0;
377 switch (Ty->getTypeID()) {
378 // Integer constant, expanding for stack operations.
379 case Type::IntegerTyID:
380 NumBits = getBitWidth(Ty);
381 // Expand integer value to "int32" or "int64".
382 if (Expand) return (NumBits<=32 ? "i4" : "i8");
383 if (NumBits==1) return "i1";
384 return (isSigned ? "i" : "u")+utostr(NumBits/8);
385 // Float constant.
386 case Type::FloatTyID:
387 return "r4";
388 case Type::DoubleTyID:
389 return "r8";
390 case Type::PointerTyID:
Duncan Sands777d2302009-05-09 07:06:46 +0000391 return "i"+utostr(TD->getTypeAllocSize(Ty));
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000392 default:
393 cerr << "TypeID = " << Ty->getTypeID() << '\n';
394 assert(0 && "Invalid type in TypeToPostfix()");
395 }
Chris Lattnerd27c9912008-03-30 18:22:13 +0000396 return ""; // Not reached
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000397}
398
399
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000400void MSILWriter::printConvToPtr() {
401 switch (ModulePtr->getPointerSize()) {
402 case Module::Pointer32:
403 printSimpleInstruction("conv.u4");
404 break;
405 case Module::Pointer64:
406 printSimpleInstruction("conv.u8");
407 break;
408 default:
409 assert(0 && "Module use not supporting pointer size");
410 }
411}
412
413
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000414void MSILWriter::printPtrLoad(uint64_t N) {
415 switch (ModulePtr->getPointerSize()) {
416 case Module::Pointer32:
417 printSimpleInstruction("ldc.i4",utostr(N).c_str());
418 // FIXME: Need overflow test?
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000419 if (!isUInt32(N)) {
420 cerr << "Value = " << utostr(N) << '\n';
421 assert(0 && "32-bit pointer overflowed");
422 }
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000423 break;
424 case Module::Pointer64:
425 printSimpleInstruction("ldc.i8",utostr(N).c_str());
426 break;
427 default:
428 assert(0 && "Module use not supporting pointer size");
429 }
430}
431
432
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000433void MSILWriter::printValuePtrLoad(const Value* V) {
434 printValueLoad(V);
435 printConvToPtr();
436}
437
438
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000439void MSILWriter::printConstLoad(const Constant* C) {
440 if (const ConstantInt* CInt = dyn_cast<ConstantInt>(C)) {
441 // Integer constant
442 Out << "\tldc." << getTypePostfix(C->getType(),true) << '\t';
443 if (CInt->isMinValue(true))
444 Out << CInt->getSExtValue();
445 else
446 Out << CInt->getZExtValue();
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000447 } else if (const ConstantFP* FP = dyn_cast<ConstantFP>(C)) {
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000448 // Float constant
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000449 uint64_t X;
450 unsigned Size;
451 if (FP->getType()->getTypeID()==Type::FloatTyID) {
Dale Johannesen7111b022008-10-09 18:53:47 +0000452 X = (uint32_t)FP->getValueAPF().bitcastToAPInt().getZExtValue();
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000453 Size = 4;
454 } else {
Dale Johannesen7111b022008-10-09 18:53:47 +0000455 X = FP->getValueAPF().bitcastToAPInt().getZExtValue();
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000456 Size = 8;
457 }
458 Out << "\tldc.r" << Size << "\t( " << utohexstr(X) << ')';
459 } else if (isa<UndefValue>(C)) {
460 // Undefined constant value = NULL.
461 printPtrLoad(0);
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000462 } else {
463 cerr << "Constant = " << *C << '\n';
464 assert(0 && "Invalid constant value");
465 }
466 Out << '\n';
467}
468
469
470void MSILWriter::printValueLoad(const Value* V) {
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000471 MSILWriter::ValueType Location = getValueLocation(V);
472 switch (Location) {
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000473 // Global variable or function address.
474 case GlobalVT:
475 case InternalVT:
476 if (const Function* F = dyn_cast<Function>(V)) {
477 std::string Name = getConvModopt(F->getCallingConv())+getValueName(F);
478 printSimpleInstruction("ldftn",
479 getCallSignature(F->getFunctionType(),NULL,Name).c_str());
480 } else {
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000481 std::string Tmp;
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000482 const Type* ElemTy = cast<PointerType>(V->getType())->getElementType();
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000483 if (Location==GlobalVT && cast<GlobalVariable>(V)->hasDLLImportLinkage()) {
484 Tmp = "void* "+getValueName(V);
485 printSimpleInstruction("ldsfld",Tmp.c_str());
486 } else {
487 Tmp = getTypeName(ElemTy)+getValueName(V);
488 printSimpleInstruction("ldsflda",Tmp.c_str());
489 }
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000490 }
491 break;
492 // Function argument.
493 case ArgumentVT:
494 printSimpleInstruction("ldarg",getValueName(V).c_str());
495 break;
496 // Local function variable.
497 case LocalVT:
498 printSimpleInstruction("ldloc",getValueName(V).c_str());
499 break;
500 // Constant value.
501 case ConstVT:
502 if (isa<ConstantPointerNull>(V))
503 printPtrLoad(0);
504 else
505 printConstLoad(cast<Constant>(V));
506 break;
507 // Constant expression.
508 case ConstExprVT:
509 printConstantExpr(cast<ConstantExpr>(V));
510 break;
511 default:
512 cerr << "Value = " << *V << '\n';
513 assert(0 && "Invalid value location");
514 }
515}
516
517
518void MSILWriter::printValueSave(const Value* V) {
519 switch (getValueLocation(V)) {
520 case ArgumentVT:
521 printSimpleInstruction("starg",getValueName(V).c_str());
522 break;
523 case LocalVT:
524 printSimpleInstruction("stloc",getValueName(V).c_str());
525 break;
526 default:
527 cerr << "Value = " << *V << '\n';
528 assert(0 && "Invalid value location");
529 }
530}
531
532
533void MSILWriter::printBinaryInstruction(const char* Name, const Value* Left,
534 const Value* Right) {
535 printValueLoad(Left);
536 printValueLoad(Right);
537 Out << '\t' << Name << '\n';
538}
539
540
541void MSILWriter::printSimpleInstruction(const char* Inst, const char* Operand) {
542 if(Operand)
543 Out << '\t' << Inst << '\t' << Operand << '\n';
544 else
545 Out << '\t' << Inst << '\n';
546}
547
548
549void MSILWriter::printPHICopy(const BasicBlock* Src, const BasicBlock* Dst) {
550 for (BasicBlock::const_iterator I = Dst->begin(), E = Dst->end();
551 isa<PHINode>(I); ++I) {
552 const PHINode* Phi = cast<PHINode>(I);
553 const Value* Val = Phi->getIncomingValueForBlock(Src);
554 if (isa<UndefValue>(Val)) continue;
555 printValueLoad(Val);
556 printValueSave(Phi);
557 }
558}
559
560
561void MSILWriter::printBranchToBlock(const BasicBlock* CurrBB,
562 const BasicBlock* TrueBB,
563 const BasicBlock* FalseBB) {
564 if (TrueBB==FalseBB) {
565 // "TrueBB" and "FalseBB" destination equals
566 printPHICopy(CurrBB,TrueBB);
567 printSimpleInstruction("pop");
568 printSimpleInstruction("br",getLabelName(TrueBB).c_str());
569 } else if (FalseBB==NULL) {
570 // If "FalseBB" not used the jump have condition
571 printPHICopy(CurrBB,TrueBB);
572 printSimpleInstruction("brtrue",getLabelName(TrueBB).c_str());
573 } else if (TrueBB==NULL) {
574 // If "TrueBB" not used the jump is unconditional
575 printPHICopy(CurrBB,FalseBB);
576 printSimpleInstruction("br",getLabelName(FalseBB).c_str());
577 } else {
578 // Copy PHI instructions for each block
579 std::string TmpLabel;
580 // Print PHI instructions for "TrueBB"
581 if (isa<PHINode>(TrueBB->begin())) {
582 TmpLabel = getLabelName(TrueBB)+"$phi_"+utostr(getUniqID());
583 printSimpleInstruction("brtrue",TmpLabel.c_str());
584 } else {
585 printSimpleInstruction("brtrue",getLabelName(TrueBB).c_str());
586 }
587 // Print PHI instructions for "FalseBB"
588 if (isa<PHINode>(FalseBB->begin())) {
589 printPHICopy(CurrBB,FalseBB);
590 printSimpleInstruction("br",getLabelName(FalseBB).c_str());
591 } else {
592 printSimpleInstruction("br",getLabelName(FalseBB).c_str());
593 }
594 if (isa<PHINode>(TrueBB->begin())) {
595 // Handle "TrueBB" PHI Copy
596 Out << TmpLabel << ":\n";
597 printPHICopy(CurrBB,TrueBB);
598 printSimpleInstruction("br",getLabelName(TrueBB).c_str());
599 }
600 }
601}
602
603
604void MSILWriter::printBranchInstruction(const BranchInst* Inst) {
605 if (Inst->isUnconditional()) {
606 printBranchToBlock(Inst->getParent(),NULL,Inst->getSuccessor(0));
607 } else {
608 printValueLoad(Inst->getCondition());
609 printBranchToBlock(Inst->getParent(),Inst->getSuccessor(0),
610 Inst->getSuccessor(1));
611 }
612}
613
614
615void MSILWriter::printSelectInstruction(const Value* Cond, const Value* VTrue,
616 const Value* VFalse) {
617 std::string TmpLabel = std::string("select$true_")+utostr(getUniqID());
618 printValueLoad(VTrue);
619 printValueLoad(Cond);
620 printSimpleInstruction("brtrue",TmpLabel.c_str());
621 printSimpleInstruction("pop");
622 printValueLoad(VFalse);
623 Out << TmpLabel << ":\n";
624}
625
626
627void MSILWriter::printIndirectLoad(const Value* V) {
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000628 const Type* Ty = V->getType();
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000629 printValueLoad(V);
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000630 if (const PointerType* P = dyn_cast<PointerType>(Ty))
631 Ty = P->getElementType();
632 std::string Tmp = "ldind."+getTypePostfix(Ty, false);
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000633 printSimpleInstruction(Tmp.c_str());
634}
635
636
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000637void MSILWriter::printIndirectSave(const Value* Ptr, const Value* Val) {
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000638 printValueLoad(Ptr);
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000639 printValueLoad(Val);
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000640 printIndirectSave(Val->getType());
641}
642
643
644void MSILWriter::printIndirectSave(const Type* Ty) {
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000645 // Instruction need signed postfix for any type.
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000646 std::string postfix = getTypePostfix(Ty, false);
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000647 if (*postfix.begin()=='u') *postfix.begin() = 'i';
648 postfix = "stind."+postfix;
649 printSimpleInstruction(postfix.c_str());
650}
651
652
653void MSILWriter::printCastInstruction(unsigned int Op, const Value* V,
654 const Type* Ty) {
655 std::string Tmp("");
656 printValueLoad(V);
657 switch (Op) {
658 // Signed
659 case Instruction::SExt:
660 case Instruction::SIToFP:
661 case Instruction::FPToSI:
662 Tmp = "conv."+getTypePostfix(Ty,false,true);
663 printSimpleInstruction(Tmp.c_str());
664 break;
665 // Unsigned
666 case Instruction::FPTrunc:
667 case Instruction::FPExt:
668 case Instruction::UIToFP:
669 case Instruction::Trunc:
670 case Instruction::ZExt:
671 case Instruction::FPToUI:
672 case Instruction::PtrToInt:
673 case Instruction::IntToPtr:
674 Tmp = "conv."+getTypePostfix(Ty,false);
675 printSimpleInstruction(Tmp.c_str());
676 break;
677 // Do nothing
678 case Instruction::BitCast:
679 // FIXME: meaning that ld*/st* instruction do not change data format.
680 break;
681 default:
682 cerr << "Opcode = " << Op << '\n';
683 assert(0 && "Invalid conversion instruction");
684 }
685}
686
687
688void MSILWriter::printGepInstruction(const Value* V, gep_type_iterator I,
689 gep_type_iterator E) {
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000690 unsigned Size;
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000691 // Load address
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000692 printValuePtrLoad(V);
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000693 // Calculate element offset.
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000694 for (; I!=E; ++I){
695 Size = 0;
696 const Value* IndexValue = I.getOperand();
697 if (const StructType* StrucTy = dyn_cast<StructType>(*I)) {
698 uint64_t FieldIndex = cast<ConstantInt>(IndexValue)->getZExtValue();
699 // Offset is the sum of all previous structure fields.
700 for (uint64_t F = 0; F<FieldIndex; ++F)
Duncan Sands777d2302009-05-09 07:06:46 +0000701 Size += TD->getTypeAllocSize(StrucTy->getContainedType((unsigned)F));
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000702 printPtrLoad(Size);
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000703 printSimpleInstruction("add");
704 continue;
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000705 } else if (const SequentialType* SeqTy = dyn_cast<SequentialType>(*I)) {
Duncan Sands777d2302009-05-09 07:06:46 +0000706 Size = TD->getTypeAllocSize(SeqTy->getElementType());
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000707 } else {
Duncan Sands777d2302009-05-09 07:06:46 +0000708 Size = TD->getTypeAllocSize(*I);
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000709 }
710 // Add offset of current element to stack top.
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000711 if (!isZeroValue(IndexValue)) {
712 // Constant optimization.
713 if (const ConstantInt* C = dyn_cast<ConstantInt>(IndexValue)) {
714 if (C->getValue().isNegative()) {
715 printPtrLoad(C->getValue().abs().getZExtValue()*Size);
716 printSimpleInstruction("sub");
717 continue;
718 } else
719 printPtrLoad(C->getZExtValue()*Size);
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000720 } else {
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000721 printPtrLoad(Size);
722 printValuePtrLoad(IndexValue);
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000723 printSimpleInstruction("mul");
724 }
725 printSimpleInstruction("add");
726 }
727 }
728}
729
730
731std::string MSILWriter::getCallSignature(const FunctionType* Ty,
732 const Instruction* Inst,
733 std::string Name) {
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000734 std::string Tmp("");
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000735 if (Ty->isVarArg()) Tmp += "vararg ";
736 // Name and return type.
737 Tmp += getTypeName(Ty->getReturnType())+Name+"(";
738 // Function argument type list.
739 unsigned NumParams = Ty->getNumParams();
740 for (unsigned I = 0; I!=NumParams; ++I) {
741 if (I!=0) Tmp += ",";
742 Tmp += getTypeName(Ty->getParamType(I));
743 }
744 // CLR needs to know the exact amount of parameters received by vararg
745 // function, because caller cleans the stack.
746 if (Ty->isVarArg() && Inst) {
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000747 // Origin to function arguments in "CallInst" or "InvokeInst".
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000748 unsigned Org = isa<InvokeInst>(Inst) ? 3 : 1;
749 // Print variable argument types.
750 unsigned NumOperands = Inst->getNumOperands()-Org;
751 if (NumParams<NumOperands) {
752 if (NumParams!=0) Tmp += ", ";
753 Tmp += "... , ";
754 for (unsigned J = NumParams; J!=NumOperands; ++J) {
755 if (J!=NumParams) Tmp += ", ";
756 Tmp += getTypeName(Inst->getOperand(J+Org)->getType());
757 }
758 }
759 }
760 return Tmp+")";
761}
762
763
764void MSILWriter::printFunctionCall(const Value* FnVal,
765 const Instruction* Inst) {
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000766 // Get function calling convention.
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000767 std::string Name = "";
768 if (const CallInst* Call = dyn_cast<CallInst>(Inst))
769 Name = getConvModopt(Call->getCallingConv());
770 else if (const InvokeInst* Invoke = dyn_cast<InvokeInst>(Inst))
771 Name = getConvModopt(Invoke->getCallingConv());
772 else {
773 cerr << "Instruction = " << Inst->getName() << '\n';
774 assert(0 && "Need \"Invoke\" or \"Call\" instruction only");
775 }
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000776 if (const Function* F = dyn_cast<Function>(FnVal)) {
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000777 // Direct call.
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000778 Name += getValueName(F);
779 printSimpleInstruction("call",
780 getCallSignature(F->getFunctionType(),Inst,Name).c_str());
781 } else {
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000782 // Indirect function call.
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000783 const PointerType* PTy = cast<PointerType>(FnVal->getType());
784 const FunctionType* FTy = cast<FunctionType>(PTy->getElementType());
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000785 // Load function address.
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000786 printValueLoad(FnVal);
787 printSimpleInstruction("calli",getCallSignature(FTy,Inst,Name).c_str());
788 }
789}
790
791
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000792void MSILWriter::printIntrinsicCall(const IntrinsicInst* Inst) {
793 std::string Name;
794 switch (Inst->getIntrinsicID()) {
795 case Intrinsic::vastart:
796 Name = getValueName(Inst->getOperand(1));
797 Name.insert(Name.length()-1,"$valist");
798 // Obtain the argument handle.
799 printSimpleInstruction("ldloca",Name.c_str());
800 printSimpleInstruction("arglist");
801 printSimpleInstruction("call",
802 "instance void [mscorlib]System.ArgIterator::.ctor"
803 "(valuetype [mscorlib]System.RuntimeArgumentHandle)");
804 // Save as pointer type "void*"
805 printValueLoad(Inst->getOperand(1));
806 printSimpleInstruction("ldloca",Name.c_str());
Christopher Lamb43ad6b32007-12-17 01:12:55 +0000807 printIndirectSave(PointerType::getUnqual(IntegerType::get(8)));
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000808 break;
809 case Intrinsic::vaend:
810 // Close argument list handle.
811 printIndirectLoad(Inst->getOperand(1));
812 printSimpleInstruction("call","instance void [mscorlib]System.ArgIterator::End()");
813 break;
814 case Intrinsic::vacopy:
815 // Copy "ArgIterator" valuetype.
816 printIndirectLoad(Inst->getOperand(1));
817 printIndirectLoad(Inst->getOperand(2));
818 printSimpleInstruction("cpobj","[mscorlib]System.ArgIterator");
819 break;
820 default:
821 cerr << "Intrinsic ID = " << Inst->getIntrinsicID() << '\n';
822 assert(0 && "Invalid intrinsic function");
823 }
824}
825
826
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000827void MSILWriter::printCallInstruction(const Instruction* Inst) {
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000828 if (isa<IntrinsicInst>(Inst)) {
829 // Handle intrinsic function.
830 printIntrinsicCall(cast<IntrinsicInst>(Inst));
831 } else {
832 // Load arguments to stack and call function.
833 for (int I = 1, E = Inst->getNumOperands(); I!=E; ++I)
834 printValueLoad(Inst->getOperand(I));
835 printFunctionCall(Inst->getOperand(0),Inst);
836 }
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000837}
838
839
840void MSILWriter::printICmpInstruction(unsigned Predicate, const Value* Left,
841 const Value* Right) {
842 switch (Predicate) {
843 case ICmpInst::ICMP_EQ:
844 printBinaryInstruction("ceq",Left,Right);
845 break;
846 case ICmpInst::ICMP_NE:
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000847 // Emulate = not neg (Op1 eq Op2)
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000848 printBinaryInstruction("ceq",Left,Right);
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000849 printSimpleInstruction("neg");
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000850 printSimpleInstruction("not");
851 break;
852 case ICmpInst::ICMP_ULE:
853 case ICmpInst::ICMP_SLE:
854 // Emulate = (Op1 eq Op2) or (Op1 lt Op2)
855 printBinaryInstruction("ceq",Left,Right);
856 if (Predicate==ICmpInst::ICMP_ULE)
857 printBinaryInstruction("clt.un",Left,Right);
858 else
859 printBinaryInstruction("clt",Left,Right);
860 printSimpleInstruction("or");
861 break;
862 case ICmpInst::ICMP_UGE:
863 case ICmpInst::ICMP_SGE:
864 // Emulate = (Op1 eq Op2) or (Op1 gt Op2)
865 printBinaryInstruction("ceq",Left,Right);
866 if (Predicate==ICmpInst::ICMP_UGE)
867 printBinaryInstruction("cgt.un",Left,Right);
868 else
869 printBinaryInstruction("cgt",Left,Right);
870 printSimpleInstruction("or");
871 break;
872 case ICmpInst::ICMP_ULT:
873 printBinaryInstruction("clt.un",Left,Right);
874 break;
875 case ICmpInst::ICMP_SLT:
876 printBinaryInstruction("clt",Left,Right);
877 break;
878 case ICmpInst::ICMP_UGT:
879 printBinaryInstruction("cgt.un",Left,Right);
880 case ICmpInst::ICMP_SGT:
881 printBinaryInstruction("cgt",Left,Right);
882 break;
883 default:
884 cerr << "Predicate = " << Predicate << '\n';
885 assert(0 && "Invalid icmp predicate");
886 }
887}
888
889
890void MSILWriter::printFCmpInstruction(unsigned Predicate, const Value* Left,
891 const Value* Right) {
892 // FIXME: Correct comparison
893 std::string NanFunc = "bool [mscorlib]System.Double::IsNaN(float64)";
894 switch (Predicate) {
895 case FCmpInst::FCMP_UGT:
896 // X > Y || llvm_fcmp_uno(X, Y)
897 printBinaryInstruction("cgt",Left,Right);
898 printFCmpInstruction(FCmpInst::FCMP_UNO,Left,Right);
899 printSimpleInstruction("or");
900 break;
901 case FCmpInst::FCMP_OGT:
902 // X > Y
903 printBinaryInstruction("cgt",Left,Right);
904 break;
905 case FCmpInst::FCMP_UGE:
906 // X >= Y || llvm_fcmp_uno(X, Y)
907 printBinaryInstruction("ceq",Left,Right);
908 printBinaryInstruction("cgt",Left,Right);
909 printSimpleInstruction("or");
910 printFCmpInstruction(FCmpInst::FCMP_UNO,Left,Right);
911 printSimpleInstruction("or");
912 break;
913 case FCmpInst::FCMP_OGE:
914 // X >= Y
915 printBinaryInstruction("ceq",Left,Right);
916 printBinaryInstruction("cgt",Left,Right);
917 printSimpleInstruction("or");
918 break;
919 case FCmpInst::FCMP_ULT:
920 // X < Y || llvm_fcmp_uno(X, Y)
921 printBinaryInstruction("clt",Left,Right);
922 printFCmpInstruction(FCmpInst::FCMP_UNO,Left,Right);
923 printSimpleInstruction("or");
924 break;
925 case FCmpInst::FCMP_OLT:
926 // X < Y
927 printBinaryInstruction("clt",Left,Right);
928 break;
929 case FCmpInst::FCMP_ULE:
930 // X <= Y || llvm_fcmp_uno(X, Y)
931 printBinaryInstruction("ceq",Left,Right);
932 printBinaryInstruction("clt",Left,Right);
933 printSimpleInstruction("or");
934 printFCmpInstruction(FCmpInst::FCMP_UNO,Left,Right);
935 printSimpleInstruction("or");
936 break;
937 case FCmpInst::FCMP_OLE:
938 // X <= Y
939 printBinaryInstruction("ceq",Left,Right);
940 printBinaryInstruction("clt",Left,Right);
941 printSimpleInstruction("or");
942 break;
943 case FCmpInst::FCMP_UEQ:
944 // X == Y || llvm_fcmp_uno(X, Y)
945 printBinaryInstruction("ceq",Left,Right);
946 printFCmpInstruction(FCmpInst::FCMP_UNO,Left,Right);
947 printSimpleInstruction("or");
948 break;
949 case FCmpInst::FCMP_OEQ:
950 // X == Y
951 printBinaryInstruction("ceq",Left,Right);
952 break;
953 case FCmpInst::FCMP_UNE:
954 // X != Y
955 printBinaryInstruction("ceq",Left,Right);
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000956 printSimpleInstruction("neg");
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000957 printSimpleInstruction("not");
958 break;
959 case FCmpInst::FCMP_ONE:
960 // X != Y && llvm_fcmp_ord(X, Y)
961 printBinaryInstruction("ceq",Left,Right);
962 printSimpleInstruction("not");
963 break;
964 case FCmpInst::FCMP_ORD:
965 // return X == X && Y == Y
966 printBinaryInstruction("ceq",Left,Left);
967 printBinaryInstruction("ceq",Right,Right);
968 printSimpleInstruction("or");
969 break;
970 case FCmpInst::FCMP_UNO:
971 // X != X || Y != Y
972 printBinaryInstruction("ceq",Left,Left);
973 printSimpleInstruction("not");
974 printBinaryInstruction("ceq",Right,Right);
975 printSimpleInstruction("not");
976 printSimpleInstruction("or");
977 break;
978 default:
979 assert(0 && "Illegal FCmp predicate");
980 }
981}
982
983
984void MSILWriter::printInvokeInstruction(const InvokeInst* Inst) {
985 std::string Label = "leave$normal_"+utostr(getUniqID());
986 Out << ".try {\n";
987 // Load arguments
988 for (int I = 3, E = Inst->getNumOperands(); I!=E; ++I)
989 printValueLoad(Inst->getOperand(I));
990 // Print call instruction
991 printFunctionCall(Inst->getOperand(0),Inst);
992 // Save function result and leave "try" block
993 printValueSave(Inst);
994 printSimpleInstruction("leave",Label.c_str());
995 Out << "}\n";
996 Out << "catch [mscorlib]System.Exception {\n";
997 // Redirect to unwind block
998 printSimpleInstruction("pop");
999 printBranchToBlock(Inst->getParent(),NULL,Inst->getUnwindDest());
1000 Out << "}\n" << Label << ":\n";
1001 // Redirect to continue block
1002 printBranchToBlock(Inst->getParent(),NULL,Inst->getNormalDest());
1003}
1004
1005
1006void MSILWriter::printSwitchInstruction(const SwitchInst* Inst) {
1007 // FIXME: Emulate with IL "switch" instruction
1008 // Emulate = if () else if () else if () else ...
1009 for (unsigned int I = 1, E = Inst->getNumCases(); I!=E; ++I) {
1010 printValueLoad(Inst->getCondition());
1011 printValueLoad(Inst->getCaseValue(I));
1012 printSimpleInstruction("ceq");
1013 // Condition jump to successor block
1014 printBranchToBlock(Inst->getParent(),Inst->getSuccessor(I),NULL);
1015 }
1016 // Jump to default block
1017 printBranchToBlock(Inst->getParent(),NULL,Inst->getDefaultDest());
1018}
1019
1020
Anton Korobeynikovf13090c2007-05-06 20:13:33 +00001021void MSILWriter::printVAArgInstruction(const VAArgInst* Inst) {
1022 printIndirectLoad(Inst->getOperand(0));
1023 printSimpleInstruction("call",
1024 "instance typedref [mscorlib]System.ArgIterator::GetNextArg()");
1025 printSimpleInstruction("refanyval","void*");
Christopher Lamb43ad6b32007-12-17 01:12:55 +00001026 std::string Name =
1027 "ldind."+getTypePostfix(PointerType::getUnqual(IntegerType::get(8)),false);
Anton Korobeynikovf13090c2007-05-06 20:13:33 +00001028 printSimpleInstruction(Name.c_str());
1029}
1030
1031
1032void MSILWriter::printAllocaInstruction(const AllocaInst* Inst) {
Duncan Sands777d2302009-05-09 07:06:46 +00001033 uint64_t Size = TD->getTypeAllocSize(Inst->getAllocatedType());
Anton Korobeynikovf13090c2007-05-06 20:13:33 +00001034 // Constant optimization.
1035 if (const ConstantInt* CInt = dyn_cast<ConstantInt>(Inst->getOperand(0))) {
1036 printPtrLoad(CInt->getZExtValue()*Size);
1037 } else {
1038 printPtrLoad(Size);
1039 printValueLoad(Inst->getOperand(0));
1040 printSimpleInstruction("mul");
1041 }
1042 printSimpleInstruction("localloc");
1043}
1044
1045
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001046void MSILWriter::printInstruction(const Instruction* Inst) {
1047 const Value *Left = 0, *Right = 0;
1048 if (Inst->getNumOperands()>=1) Left = Inst->getOperand(0);
1049 if (Inst->getNumOperands()>=2) Right = Inst->getOperand(1);
1050 // Print instruction
Anton Korobeynikovf13090c2007-05-06 20:13:33 +00001051 // FIXME: "ShuffleVector","ExtractElement","InsertElement" support.
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001052 switch (Inst->getOpcode()) {
1053 // Terminator
1054 case Instruction::Ret:
1055 if (Inst->getNumOperands()) {
1056 printValueLoad(Left);
1057 printSimpleInstruction("ret");
1058 } else
1059 printSimpleInstruction("ret");
1060 break;
1061 case Instruction::Br:
1062 printBranchInstruction(cast<BranchInst>(Inst));
1063 break;
1064 // Binary
1065 case Instruction::Add:
Dan Gohmanae3a0be2009-06-04 22:49:04 +00001066 case Instruction::FAdd:
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001067 printBinaryInstruction("add",Left,Right);
1068 break;
1069 case Instruction::Sub:
Dan Gohmanae3a0be2009-06-04 22:49:04 +00001070 case Instruction::FSub:
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001071 printBinaryInstruction("sub",Left,Right);
1072 break;
Dan Gohmanae3a0be2009-06-04 22:49:04 +00001073 case Instruction::Mul:
1074 case Instruction::FMul:
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001075 printBinaryInstruction("mul",Left,Right);
1076 break;
1077 case Instruction::UDiv:
1078 printBinaryInstruction("div.un",Left,Right);
1079 break;
1080 case Instruction::SDiv:
1081 case Instruction::FDiv:
1082 printBinaryInstruction("div",Left,Right);
1083 break;
1084 case Instruction::URem:
1085 printBinaryInstruction("rem.un",Left,Right);
1086 break;
1087 case Instruction::SRem:
1088 case Instruction::FRem:
1089 printBinaryInstruction("rem",Left,Right);
1090 break;
1091 // Binary Condition
1092 case Instruction::ICmp:
1093 printICmpInstruction(cast<ICmpInst>(Inst)->getPredicate(),Left,Right);
1094 break;
1095 case Instruction::FCmp:
1096 printFCmpInstruction(cast<FCmpInst>(Inst)->getPredicate(),Left,Right);
1097 break;
1098 // Bitwise Binary
1099 case Instruction::And:
1100 printBinaryInstruction("and",Left,Right);
1101 break;
1102 case Instruction::Or:
1103 printBinaryInstruction("or",Left,Right);
1104 break;
1105 case Instruction::Xor:
1106 printBinaryInstruction("xor",Left,Right);
1107 break;
1108 case Instruction::Shl:
Anton Korobeynikovf13090c2007-05-06 20:13:33 +00001109 printValueLoad(Left);
1110 printValueLoad(Right);
1111 printSimpleInstruction("conv.i4");
1112 printSimpleInstruction("shl");
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001113 break;
1114 case Instruction::LShr:
Anton Korobeynikovf13090c2007-05-06 20:13:33 +00001115 printValueLoad(Left);
1116 printValueLoad(Right);
1117 printSimpleInstruction("conv.i4");
1118 printSimpleInstruction("shr.un");
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001119 break;
1120 case Instruction::AShr:
Anton Korobeynikovf13090c2007-05-06 20:13:33 +00001121 printValueLoad(Left);
1122 printValueLoad(Right);
1123 printSimpleInstruction("conv.i4");
1124 printSimpleInstruction("shr");
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001125 break;
1126 case Instruction::Select:
1127 printSelectInstruction(Inst->getOperand(0),Inst->getOperand(1),Inst->getOperand(2));
1128 break;
1129 case Instruction::Load:
1130 printIndirectLoad(Inst->getOperand(0));
1131 break;
1132 case Instruction::Store:
Anton Korobeynikovf13090c2007-05-06 20:13:33 +00001133 printIndirectSave(Inst->getOperand(1), Inst->getOperand(0));
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001134 break;
1135 case Instruction::Trunc:
1136 case Instruction::ZExt:
1137 case Instruction::SExt:
1138 case Instruction::FPTrunc:
1139 case Instruction::FPExt:
1140 case Instruction::UIToFP:
1141 case Instruction::SIToFP:
1142 case Instruction::FPToUI:
1143 case Instruction::FPToSI:
1144 case Instruction::PtrToInt:
1145 case Instruction::IntToPtr:
1146 case Instruction::BitCast:
1147 printCastInstruction(Inst->getOpcode(),Left,
1148 cast<CastInst>(Inst)->getDestTy());
1149 break;
1150 case Instruction::GetElementPtr:
1151 printGepInstruction(Inst->getOperand(0),gep_type_begin(Inst),
1152 gep_type_end(Inst));
1153 break;
1154 case Instruction::Call:
1155 printCallInstruction(cast<CallInst>(Inst));
1156 break;
1157 case Instruction::Invoke:
1158 printInvokeInstruction(cast<InvokeInst>(Inst));
1159 break;
Anton Korobeynikovf13090c2007-05-06 20:13:33 +00001160 case Instruction::Unwind:
1161 printSimpleInstruction("newobj",
1162 "instance void [mscorlib]System.Exception::.ctor()");
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001163 printSimpleInstruction("throw");
1164 break;
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001165 case Instruction::Switch:
1166 printSwitchInstruction(cast<SwitchInst>(Inst));
1167 break;
1168 case Instruction::Alloca:
Anton Korobeynikovf13090c2007-05-06 20:13:33 +00001169 printAllocaInstruction(cast<AllocaInst>(Inst));
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001170 break;
1171 case Instruction::Malloc:
1172 assert(0 && "LowerAllocationsPass used");
1173 break;
1174 case Instruction::Free:
1175 assert(0 && "LowerAllocationsPass used");
1176 break;
1177 case Instruction::Unreachable:
Anton Korobeynikovf13090c2007-05-06 20:13:33 +00001178 printSimpleInstruction("ldstr", "\"Unreachable instruction\"");
1179 printSimpleInstruction("newobj",
1180 "instance void [mscorlib]System.Exception::.ctor(string)");
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001181 printSimpleInstruction("throw");
1182 break;
Anton Korobeynikovf13090c2007-05-06 20:13:33 +00001183 case Instruction::VAArg:
1184 printVAArgInstruction(cast<VAArgInst>(Inst));
1185 break;
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001186 default:
1187 cerr << "Instruction = " << Inst->getName() << '\n';
1188 assert(0 && "Unsupported instruction");
1189 }
1190}
1191
1192
1193void MSILWriter::printLoop(const Loop* L) {
1194 Out << getLabelName(L->getHeader()->getName()) << ":\n";
1195 const std::vector<BasicBlock*>& blocks = L->getBlocks();
1196 for (unsigned I = 0, E = blocks.size(); I!=E; I++) {
1197 BasicBlock* BB = blocks[I];
1198 Loop* BBLoop = LInfo->getLoopFor(BB);
1199 if (BBLoop == L)
1200 printBasicBlock(BB);
1201 else if (BB==BBLoop->getHeader() && BBLoop->getParentLoop()==L)
1202 printLoop(BBLoop);
1203 }
1204 printSimpleInstruction("br",getLabelName(L->getHeader()->getName()).c_str());
1205}
1206
1207
1208void MSILWriter::printBasicBlock(const BasicBlock* BB) {
1209 Out << getLabelName(BB) << ":\n";
1210 for (BasicBlock::const_iterator I = BB->begin(), E = BB->end(); I!=E; ++I) {
1211 const Instruction* Inst = I;
1212 // Comment llvm original instruction
Owen Andersoncb371882008-08-21 00:14:44 +00001213 // Out << "\n//" << *Inst << "\n";
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001214 // Do not handle PHI instruction in current block
1215 if (Inst->getOpcode()==Instruction::PHI) continue;
1216 // Print instruction
1217 printInstruction(Inst);
1218 // Save result
1219 if (Inst->getType()!=Type::VoidTy) {
1220 // Do not save value after invoke, it done in "try" block
1221 if (Inst->getOpcode()==Instruction::Invoke) continue;
1222 printValueSave(Inst);
1223 }
1224 }
1225}
1226
1227
1228void MSILWriter::printLocalVariables(const Function& F) {
1229 std::string Name;
1230 const Type* Ty = NULL;
Anton Korobeynikovf13090c2007-05-06 20:13:33 +00001231 std::set<const Value*> Printed;
1232 const Value* VaList = NULL;
1233 unsigned StackDepth = 8;
1234 // Find local variables
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001235 for (const_inst_iterator I = inst_begin(&F), E = inst_end(&F); I!=E; ++I) {
Anton Korobeynikovf13090c2007-05-06 20:13:33 +00001236 if (I->getOpcode()==Instruction::Call ||
1237 I->getOpcode()==Instruction::Invoke) {
1238 // Test stack depth.
1239 if (StackDepth<I->getNumOperands())
1240 StackDepth = I->getNumOperands();
1241 }
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001242 const AllocaInst* AI = dyn_cast<AllocaInst>(&*I);
1243 if (AI && !isa<GlobalVariable>(AI)) {
Anton Korobeynikovf13090c2007-05-06 20:13:33 +00001244 // Local variable allocation.
Christopher Lamb43ad6b32007-12-17 01:12:55 +00001245 Ty = PointerType::getUnqual(AI->getAllocatedType());
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001246 Name = getValueName(AI);
Anton Korobeynikovf13090c2007-05-06 20:13:33 +00001247 Out << "\t.locals (" << getTypeName(Ty) << Name << ")\n";
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001248 } else if (I->getType()!=Type::VoidTy) {
Anton Korobeynikovf13090c2007-05-06 20:13:33 +00001249 // Operation result.
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001250 Ty = I->getType();
1251 Name = getValueName(&*I);
Anton Korobeynikovf13090c2007-05-06 20:13:33 +00001252 Out << "\t.locals (" << getTypeName(Ty) << Name << ")\n";
1253 }
1254 // Test on 'va_list' variable
1255 bool isVaList = false;
1256 if (const VAArgInst* VaInst = dyn_cast<VAArgInst>(&*I)) {
1257 // "va_list" as "va_arg" instruction operand.
1258 isVaList = true;
1259 VaList = VaInst->getOperand(0);
1260 } else if (const IntrinsicInst* Inst = dyn_cast<IntrinsicInst>(&*I)) {
1261 // "va_list" as intrinsic function operand.
1262 switch (Inst->getIntrinsicID()) {
1263 case Intrinsic::vastart:
1264 case Intrinsic::vaend:
1265 case Intrinsic::vacopy:
1266 isVaList = true;
1267 VaList = Inst->getOperand(1);
1268 break;
1269 default:
1270 isVaList = false;
1271 }
1272 }
1273 // Print "va_list" variable.
1274 if (isVaList && Printed.insert(VaList).second) {
1275 Name = getValueName(VaList);
1276 Name.insert(Name.length()-1,"$valist");
1277 Out << "\t.locals (valuetype [mscorlib]System.ArgIterator "
1278 << Name << ")\n";
1279 }
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001280 }
Anton Korobeynikovf13090c2007-05-06 20:13:33 +00001281 printSimpleInstruction(".maxstack",utostr(StackDepth*2).c_str());
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001282}
1283
1284
1285void MSILWriter::printFunctionBody(const Function& F) {
1286 // Print body
1287 for (Function::const_iterator I = F.begin(), E = F.end(); I!=E; ++I) {
1288 if (Loop *L = LInfo->getLoopFor(I)) {
1289 if (L->getHeader()==I && L->getParentLoop()==0)
1290 printLoop(L);
1291 } else {
1292 printBasicBlock(I);
1293 }
1294 }
1295}
1296
1297
1298void MSILWriter::printConstantExpr(const ConstantExpr* CE) {
1299 const Value *left = 0, *right = 0;
1300 if (CE->getNumOperands()>=1) left = CE->getOperand(0);
1301 if (CE->getNumOperands()>=2) right = CE->getOperand(1);
1302 // Print instruction
1303 switch (CE->getOpcode()) {
1304 case Instruction::Trunc:
1305 case Instruction::ZExt:
1306 case Instruction::SExt:
1307 case Instruction::FPTrunc:
1308 case Instruction::FPExt:
1309 case Instruction::UIToFP:
1310 case Instruction::SIToFP:
1311 case Instruction::FPToUI:
1312 case Instruction::FPToSI:
1313 case Instruction::PtrToInt:
1314 case Instruction::IntToPtr:
1315 case Instruction::BitCast:
1316 printCastInstruction(CE->getOpcode(),left,CE->getType());
1317 break;
1318 case Instruction::GetElementPtr:
1319 printGepInstruction(CE->getOperand(0),gep_type_begin(CE),gep_type_end(CE));
1320 break;
1321 case Instruction::ICmp:
1322 printICmpInstruction(CE->getPredicate(),left,right);
1323 break;
1324 case Instruction::FCmp:
1325 printFCmpInstruction(CE->getPredicate(),left,right);
1326 break;
1327 case Instruction::Select:
1328 printSelectInstruction(CE->getOperand(0),CE->getOperand(1),CE->getOperand(2));
1329 break;
1330 case Instruction::Add:
Dan Gohmanae3a0be2009-06-04 22:49:04 +00001331 case Instruction::FAdd:
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001332 printBinaryInstruction("add",left,right);
1333 break;
1334 case Instruction::Sub:
Dan Gohmanae3a0be2009-06-04 22:49:04 +00001335 case Instruction::FSub:
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001336 printBinaryInstruction("sub",left,right);
1337 break;
1338 case Instruction::Mul:
Dan Gohmanae3a0be2009-06-04 22:49:04 +00001339 case Instruction::FMul:
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001340 printBinaryInstruction("mul",left,right);
1341 break;
1342 case Instruction::UDiv:
1343 printBinaryInstruction("div.un",left,right);
1344 break;
1345 case Instruction::SDiv:
1346 case Instruction::FDiv:
1347 printBinaryInstruction("div",left,right);
1348 break;
1349 case Instruction::URem:
1350 printBinaryInstruction("rem.un",left,right);
1351 break;
1352 case Instruction::SRem:
1353 case Instruction::FRem:
1354 printBinaryInstruction("rem",left,right);
1355 break;
1356 case Instruction::And:
1357 printBinaryInstruction("and",left,right);
1358 break;
1359 case Instruction::Or:
1360 printBinaryInstruction("or",left,right);
1361 break;
1362 case Instruction::Xor:
1363 printBinaryInstruction("xor",left,right);
1364 break;
1365 case Instruction::Shl:
1366 printBinaryInstruction("shl",left,right);
1367 break;
1368 case Instruction::LShr:
1369 printBinaryInstruction("shr.un",left,right);
1370 break;
1371 case Instruction::AShr:
1372 printBinaryInstruction("shr",left,right);
1373 break;
1374 default:
1375 cerr << "Expression = " << *CE << "\n";
1376 assert(0 && "Invalid constant expression");
1377 }
1378}
1379
1380
1381void MSILWriter::printStaticInitializerList() {
1382 // List of global variables with uninitialized fields.
1383 for (std::map<const GlobalVariable*,std::vector<StaticInitializer> >::iterator
1384 VarI = StaticInitList.begin(), VarE = StaticInitList.end(); VarI!=VarE;
1385 ++VarI) {
1386 const std::vector<StaticInitializer>& InitList = VarI->second;
1387 if (InitList.empty()) continue;
1388 // For each uninitialized field.
1389 for (std::vector<StaticInitializer>::const_iterator I = InitList.begin(),
1390 E = InitList.end(); I!=E; ++I) {
1391 if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(I->constant)) {
Owen Andersoncb371882008-08-21 00:14:44 +00001392 // Out << "\n// Init " << getValueName(VarI->first) << ", offset " <<
1393 // utostr(I->offset) << ", type "<< *I->constant->getType() << "\n\n";
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001394 // Load variable address
1395 printValueLoad(VarI->first);
1396 // Add offset
1397 if (I->offset!=0) {
1398 printPtrLoad(I->offset);
1399 printSimpleInstruction("add");
1400 }
1401 // Load value
1402 printConstantExpr(CE);
1403 // Save result at offset
1404 std::string postfix = getTypePostfix(CE->getType(),true);
1405 if (*postfix.begin()=='u') *postfix.begin() = 'i';
1406 postfix = "stind."+postfix;
1407 printSimpleInstruction(postfix.c_str());
1408 } else {
1409 cerr << "Constant = " << *I->constant << '\n';
1410 assert(0 && "Invalid static initializer");
1411 }
1412 }
1413 }
1414}
1415
1416
1417void MSILWriter::printFunction(const Function& F) {
Devang Patel05988662008-09-25 21:00:45 +00001418 bool isSigned = F.paramHasAttr(0, Attribute::SExt);
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001419 Out << "\n.method static ";
Rafael Espindolabb46f522009-01-15 20:18:42 +00001420 Out << (F.hasLocalLinkage() ? "private " : "public ");
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001421 if (F.isVarArg()) Out << "vararg ";
1422 Out << getTypeName(F.getReturnType(),isSigned) <<
1423 getConvModopt(F.getCallingConv()) << getValueName(&F) << '\n';
1424 // Arguments
1425 Out << "\t(";
1426 unsigned ArgIdx = 1;
1427 for (Function::const_arg_iterator I = F.arg_begin(), E = F.arg_end(); I!=E;
1428 ++I, ++ArgIdx) {
Devang Patel05988662008-09-25 21:00:45 +00001429 isSigned = F.paramHasAttr(ArgIdx, Attribute::SExt);
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001430 if (I!=F.arg_begin()) Out << ", ";
1431 Out << getTypeName(I->getType(),isSigned) << getValueName(I);
1432 }
1433 Out << ") cil managed\n";
1434 // Body
1435 Out << "{\n";
Anton Korobeynikovf13090c2007-05-06 20:13:33 +00001436 printLocalVariables(F);
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001437 printFunctionBody(F);
1438 Out << "}\n";
1439}
1440
1441
1442void MSILWriter::printDeclarations(const TypeSymbolTable& ST) {
1443 std::string Name;
1444 std::set<const Type*> Printed;
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001445 for (std::set<const Type*>::const_iterator
1446 UI = UsedTypes->begin(), UE = UsedTypes->end(); UI!=UE; ++UI) {
1447 const Type* Ty = *UI;
Anton Korobeynikovf13090c2007-05-06 20:13:33 +00001448 if (isa<ArrayType>(Ty) || isa<VectorType>(Ty) || isa<StructType>(Ty))
1449 Name = getTypeName(Ty, false, true);
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001450 // Type with no need to declare.
1451 else continue;
1452 // Print not duplicated type
1453 if (Printed.insert(Ty).second) {
1454 Out << ".class value explicit ansi sealed '" << Name << "'";
Duncan Sands777d2302009-05-09 07:06:46 +00001455 Out << " { .pack " << 1 << " .size " << TD->getTypeAllocSize(Ty);
Duncan Sandsceb4d1a2009-01-12 20:38:59 +00001456 Out << " }\n\n";
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001457 }
1458 }
1459}
1460
1461
1462unsigned int MSILWriter::getBitWidth(const Type* Ty) {
1463 unsigned int N = Ty->getPrimitiveSizeInBits();
1464 assert(N!=0 && "Invalid type in getBitWidth()");
1465 switch (N) {
1466 case 1:
1467 case 8:
1468 case 16:
1469 case 32:
1470 case 64:
1471 return N;
1472 default:
1473 cerr << "Bits = " << N << '\n';
1474 assert(0 && "Unsupported integer width");
1475 }
Chris Lattnerd27c9912008-03-30 18:22:13 +00001476 return 0; // Not reached
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001477}
1478
1479
1480void MSILWriter::printStaticConstant(const Constant* C, uint64_t& Offset) {
1481 uint64_t TySize = 0;
1482 const Type* Ty = C->getType();
1483 // Print zero initialized constant.
1484 if (isa<ConstantAggregateZero>(C) || C->isNullValue()) {
Duncan Sands777d2302009-05-09 07:06:46 +00001485 TySize = TD->getTypeAllocSize(C->getType());
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001486 Offset += TySize;
1487 Out << "int8 (0) [" << TySize << "]";
1488 return;
1489 }
1490 // Print constant initializer
1491 switch (Ty->getTypeID()) {
1492 case Type::IntegerTyID: {
Duncan Sands777d2302009-05-09 07:06:46 +00001493 TySize = TD->getTypeAllocSize(Ty);
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001494 const ConstantInt* Int = cast<ConstantInt>(C);
1495 Out << getPrimitiveTypeName(Ty,true) << "(" << Int->getSExtValue() << ")";
1496 break;
1497 }
1498 case Type::FloatTyID:
1499 case Type::DoubleTyID: {
Duncan Sands777d2302009-05-09 07:06:46 +00001500 TySize = TD->getTypeAllocSize(Ty);
Anton Korobeynikovf13090c2007-05-06 20:13:33 +00001501 const ConstantFP* FP = cast<ConstantFP>(C);
1502 if (Ty->getTypeID() == Type::FloatTyID)
Dale Johannesen43421b32007-09-06 18:13:44 +00001503 Out << "int32 (" <<
Dale Johannesen7111b022008-10-09 18:53:47 +00001504 (uint32_t)FP->getValueAPF().bitcastToAPInt().getZExtValue() << ')';
Anton Korobeynikovf13090c2007-05-06 20:13:33 +00001505 else
Dale Johannesen43421b32007-09-06 18:13:44 +00001506 Out << "int64 (" <<
Dale Johannesen7111b022008-10-09 18:53:47 +00001507 FP->getValueAPF().bitcastToAPInt().getZExtValue() << ')';
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001508 break;
1509 }
1510 case Type::ArrayTyID:
1511 case Type::VectorTyID:
1512 case Type::StructTyID:
1513 for (unsigned I = 0, E = C->getNumOperands(); I<E; I++) {
1514 if (I!=0) Out << ",\n";
1515 printStaticConstant(C->getOperand(I),Offset);
1516 }
1517 break;
1518 case Type::PointerTyID:
Duncan Sands777d2302009-05-09 07:06:46 +00001519 TySize = TD->getTypeAllocSize(C->getType());
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001520 // Initialize with global variable address
1521 if (const GlobalVariable *G = dyn_cast<GlobalVariable>(C)) {
1522 std::string name = getValueName(G);
1523 Out << "&(" << name.insert(name.length()-1,"$data") << ")";
1524 } else {
1525 // Dynamic initialization
1526 if (!isa<ConstantPointerNull>(C) && !C->isNullValue())
1527 InitListPtr->push_back(StaticInitializer(C,Offset));
1528 // Null pointer initialization
1529 if (TySize==4) Out << "int32 (0)";
1530 else if (TySize==8) Out << "int64 (0)";
1531 else assert(0 && "Invalid pointer size");
1532 }
1533 break;
1534 default:
1535 cerr << "TypeID = " << Ty->getTypeID() << '\n';
1536 assert(0 && "Invalid type in printStaticConstant()");
1537 }
1538 // Increase offset.
1539 Offset += TySize;
1540}
1541
1542
1543void MSILWriter::printStaticInitializer(const Constant* C,
1544 const std::string& Name) {
1545 switch (C->getType()->getTypeID()) {
1546 case Type::IntegerTyID:
1547 case Type::FloatTyID:
1548 case Type::DoubleTyID:
Anton Korobeynikovf13090c2007-05-06 20:13:33 +00001549 Out << getPrimitiveTypeName(C->getType(), false);
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001550 break;
1551 case Type::ArrayTyID:
1552 case Type::VectorTyID:
1553 case Type::StructTyID:
1554 case Type::PointerTyID:
1555 Out << getTypeName(C->getType());
1556 break;
1557 default:
1558 cerr << "Type = " << *C << "\n";
1559 assert(0 && "Invalid constant type");
1560 }
1561 // Print initializer
1562 std::string label = Name;
1563 label.insert(label.length()-1,"$data");
1564 Out << Name << " at " << label << '\n';
1565 Out << ".data " << label << " = {\n";
1566 uint64_t offset = 0;
1567 printStaticConstant(C,offset);
1568 Out << "\n}\n\n";
1569}
1570
1571
1572void MSILWriter::printVariableDefinition(const GlobalVariable* G) {
1573 const Constant* C = G->getInitializer();
1574 if (C->isNullValue() || isa<ConstantAggregateZero>(C) || isa<UndefValue>(C))
1575 InitListPtr = 0;
1576 else
1577 InitListPtr = &StaticInitList[G];
1578 printStaticInitializer(C,getValueName(G));
1579}
1580
1581
1582void MSILWriter::printGlobalVariables() {
1583 if (ModulePtr->global_empty()) return;
1584 Module::global_iterator I,E;
1585 for (I = ModulePtr->global_begin(), E = ModulePtr->global_end(); I!=E; ++I) {
1586 // Variable definition
Anton Korobeynikovf13090c2007-05-06 20:13:33 +00001587 Out << ".field static " << (I->isDeclaration() ? "public " :
1588 "private ");
1589 if (I->isDeclaration()) {
1590 Out << getTypeName(I->getType()) << getValueName(&*I) << "\n\n";
1591 } else
1592 printVariableDefinition(&*I);
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001593 }
1594}
1595
1596
Anton Korobeynikovf13090c2007-05-06 20:13:33 +00001597const char* MSILWriter::getLibraryName(const Function* F) {
1598 return getLibraryForSymbol(F->getName().c_str(), true, F->getCallingConv());
1599}
1600
1601
1602const char* MSILWriter::getLibraryName(const GlobalVariable* GV) {
1603 return getLibraryForSymbol(Mang->getValueName(GV).c_str(), false, 0);
1604}
1605
1606
1607const char* MSILWriter::getLibraryForSymbol(const char* Name, bool isFunction,
1608 unsigned CallingConv) {
1609 // TODO: Read *.def file with function and libraries definitions.
1610 return "MSVCRT.DLL";
1611}
1612
1613
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001614void MSILWriter::printExternals() {
1615 Module::const_iterator I,E;
Anton Korobeynikovf13090c2007-05-06 20:13:33 +00001616 // Functions.
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001617 for (I=ModulePtr->begin(),E=ModulePtr->end(); I!=E; ++I) {
1618 // Skip intrisics
Duncan Sandsa3355ff2007-12-03 20:06:50 +00001619 if (I->isIntrinsic()) continue;
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001620 if (I->isDeclaration()) {
Anton Korobeynikovf13090c2007-05-06 20:13:33 +00001621 const Function* F = I;
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001622 std::string Name = getConvModopt(F->getCallingConv())+getValueName(F);
Anton Korobeynikovf13090c2007-05-06 20:13:33 +00001623 std::string Sig =
1624 getCallSignature(cast<FunctionType>(F->getFunctionType()), NULL, Name);
1625 Out << ".method static hidebysig pinvokeimpl(\""
1626 << getLibraryName(F) << "\")\n\t" << Sig << " preservesig {}\n\n";
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001627 }
1628 }
Anton Korobeynikovf13090c2007-05-06 20:13:33 +00001629 // External variables and static initialization.
1630 Out <<
1631 ".method public hidebysig static pinvokeimpl(\"KERNEL32.DLL\" ansi winapi)"
1632 " native int LoadLibrary(string) preservesig {}\n"
1633 ".method public hidebysig static pinvokeimpl(\"KERNEL32.DLL\" ansi winapi)"
1634 " native int GetProcAddress(native int, string) preservesig {}\n";
1635 Out <<
1636 ".method private static void* $MSIL_Import(string lib,string sym)\n"
1637 " managed cil\n{\n"
1638 "\tldarg\tlib\n"
1639 "\tcall\tnative int LoadLibrary(string)\n"
1640 "\tldarg\tsym\n"
1641 "\tcall\tnative int GetProcAddress(native int,string)\n"
1642 "\tdup\n"
1643 "\tbrtrue\tL_01\n"
1644 "\tldstr\t\"Can no import variable\"\n"
1645 "\tnewobj\tinstance void [mscorlib]System.Exception::.ctor(string)\n"
1646 "\tthrow\n"
1647 "L_01:\n"
1648 "\tret\n"
1649 "}\n\n"
1650 ".method static private void $MSIL_Init() managed cil\n{\n";
1651 printStaticInitializerList();
1652 // Foreach global variable.
1653 for (Module::global_iterator I = ModulePtr->global_begin(),
1654 E = ModulePtr->global_end(); I!=E; ++I) {
1655 if (!I->isDeclaration() || !I->hasDLLImportLinkage()) continue;
1656 // Use "LoadLibrary"/"GetProcAddress" to recive variable address.
1657 std::string Label = "not_null$_"+utostr(getUniqID());
1658 std::string Tmp = getTypeName(I->getType())+getValueName(&*I);
1659 printSimpleInstruction("ldsflda",Tmp.c_str());
1660 Out << "\tldstr\t\"" << getLibraryName(&*I) << "\"\n";
1661 Out << "\tldstr\t\"" << Mang->getValueName(&*I) << "\"\n";
1662 printSimpleInstruction("call","void* $MSIL_Import(string,string)");
1663 printIndirectSave(I->getType());
1664 }
1665 printSimpleInstruction("ret");
1666 Out << "}\n\n";
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001667}
1668
Anton Korobeynikovf13090c2007-05-06 20:13:33 +00001669
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001670//===----------------------------------------------------------------------===//
Bill Wendling85db3a92008-02-26 10:57:23 +00001671// External Interface declaration
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001672//===----------------------------------------------------------------------===//
1673
Owen Andersoncb371882008-08-21 00:14:44 +00001674bool MSILTarget::addPassesToEmitWholeFile(PassManager &PM, raw_ostream &o,
Bill Wendlingbe8cc2a2009-04-29 00:15:41 +00001675 CodeGenFileType FileType,
Bill Wendling98a366d2009-04-29 23:29:43 +00001676 CodeGenOpt::Level OptLevel)
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001677{
1678 if (FileType != TargetMachine::AssemblyFile) return true;
1679 MSILWriter* Writer = new MSILWriter(o);
Gordon Henriksence224772008-01-07 01:30:38 +00001680 PM.add(createGCLoweringPass());
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001681 PM.add(createLowerAllocationsPass(true));
1682 // FIXME: Handle switch trougth native IL instruction "switch"
1683 PM.add(createLowerSwitchPass());
1684 PM.add(createCFGSimplificationPass());
1685 PM.add(new MSILModule(Writer->UsedTypes,Writer->TD));
1686 PM.add(Writer);
Gordon Henriksen5eca0752008-08-17 18:44:35 +00001687 PM.add(createGCInfoDeleter());
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001688 return false;
1689}