aboutsummaryrefslogtreecommitdiff
path: root/lib/Target/MSIL/MSILWriter.cpp
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2010-08-28 16:33:36 +0000
committerChris Lattner <sabre@nondot.org>2010-08-28 16:33:36 +0000
commit885b661e1004978f39cd1d74e586f193dfc0b0a6 (patch)
treea94f664646bc8d8463cf362ef07e4e7926c05a62 /lib/Target/MSIL/MSILWriter.cpp
parent9df0a0a8711596eaa3c7dd3413c0835ad99d3929 (diff)
remove the MSIL backend. It isn't maintained, is buggy, has no testcases
and hasn't kept up with ToT. Approved by Anton. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@112375 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Target/MSIL/MSILWriter.cpp')
-rw-r--r--lib/Target/MSIL/MSILWriter.cpp1706
1 files changed, 0 insertions, 1706 deletions
diff --git a/lib/Target/MSIL/MSILWriter.cpp b/lib/Target/MSIL/MSILWriter.cpp
deleted file mode 100644
index cc350e8a4f..0000000000
--- a/lib/Target/MSIL/MSILWriter.cpp
+++ /dev/null
@@ -1,1706 +0,0 @@
-//===-- MSILWriter.cpp - Library for converting LLVM code to MSIL ---------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This library converts LLVM code to MSIL code.
-//
-//===----------------------------------------------------------------------===//
-
-#include "MSILWriter.h"
-#include "llvm/CallingConv.h"
-#include "llvm/DerivedTypes.h"
-#include "llvm/Intrinsics.h"
-#include "llvm/IntrinsicInst.h"
-#include "llvm/TypeSymbolTable.h"
-#include "llvm/Analysis/ConstantsScanner.h"
-#include "llvm/Support/CallSite.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/InstVisitor.h"
-#include "llvm/Support/MathExtras.h"
-#include "llvm/Target/TargetRegistry.h"
-#include "llvm/Transforms/Scalar.h"
-#include "llvm/ADT/StringExtras.h"
-#include "llvm/CodeGen/Passes.h"
-using namespace llvm;
-
-namespace llvm {
- // TargetMachine for the MSIL
- struct MSILTarget : public TargetMachine {
- MSILTarget(const Target &T, const std::string &TT, const std::string &FS)
- : TargetMachine(T) {}
-
- virtual bool addPassesToEmitFile(PassManagerBase &PM,
- formatted_raw_ostream &Out,
- CodeGenFileType FileType,
- CodeGenOpt::Level OptLevel,
- bool DisableVerify);
-
- virtual const TargetData *getTargetData() const { return 0; }
- };
-}
-
-extern "C" void LLVMInitializeMSILTarget() {
- // Register the target.
- RegisterTargetMachine<MSILTarget> X(TheMSILTarget);
-}
-
-bool MSILModule::runOnModule(Module &M) {
- ModulePtr = &M;
- TD = &getAnalysis<TargetData>();
- bool Changed = false;
- // Find named types.
- TypeSymbolTable& Table = M.getTypeSymbolTable();
- std::set<const Type *> Types = getAnalysis<FindUsedTypes>().getTypes();
- for (TypeSymbolTable::iterator I = Table.begin(), E = Table.end(); I!=E; ) {
- if (!I->second->isStructTy() && !I->second->isOpaqueTy())
- Table.remove(I++);
- else {
- std::set<const Type *>::iterator T = Types.find(I->second);
- if (T==Types.end())
- Table.remove(I++);
- else {
- Types.erase(T);
- ++I;
- }
- }
- }
- // Find unnamed types.
- unsigned RenameCounter = 0;
- for (std::set<const Type *>::const_iterator I = Types.begin(),
- E = Types.end(); I!=E; ++I)
- if (const StructType *STy = dyn_cast<StructType>(*I)) {
- while (ModulePtr->addTypeName("unnamed$"+utostr(RenameCounter), STy))
- ++RenameCounter;
- Changed = true;
- }
- // Pointer for FunctionPass.
- UsedTypes = &getAnalysis<FindUsedTypes>().getTypes();
- return Changed;
-}
-
-char MSILModule::ID = 0;
-char MSILWriter::ID = 0;
-
-bool MSILWriter::runOnFunction(Function &F) {
- if (F.isDeclaration()) return false;
-
- // Do not codegen any 'available_externally' functions at all, they have
- // definitions outside the translation unit.
- if (F.hasAvailableExternallyLinkage())
- return false;
-
- LInfo = &getAnalysis<LoopInfo>();
- printFunction(F);
- return false;
-}
-
-
-bool MSILWriter::doInitialization(Module &M) {
- ModulePtr = &M;
- Out << ".assembly extern mscorlib {}\n";
- Out << ".assembly MSIL {}\n\n";
- Out << "// External\n";
- printExternals();
- Out << "// Declarations\n";
- printDeclarations(M.getTypeSymbolTable());
- Out << "// Definitions\n";
- printGlobalVariables();
- Out << "// Startup code\n";
- printModuleStartup();
- return false;
-}
-
-
-bool MSILWriter::doFinalization(Module &M) {
- return false;
-}
-
-
-void MSILWriter::printModuleStartup() {
- Out <<
- ".method static public int32 $MSIL_Startup() {\n"
- "\t.entrypoint\n"
- "\t.locals (native int i)\n"
- "\t.locals (native int argc)\n"
- "\t.locals (native int ptr)\n"
- "\t.locals (void* argv)\n"
- "\t.locals (string[] args)\n"
- "\tcall\tstring[] [mscorlib]System.Environment::GetCommandLineArgs()\n"
- "\tdup\n"
- "\tstloc\targs\n"
- "\tldlen\n"
- "\tconv.i4\n"
- "\tdup\n"
- "\tstloc\targc\n";
- printPtrLoad(TD->getPointerSize());
- Out <<
- "\tmul\n"
- "\tlocalloc\n"
- "\tstloc\targv\n"
- "\tldc.i4.0\n"
- "\tstloc\ti\n"
- "L_01:\n"
- "\tldloc\ti\n"
- "\tldloc\targc\n"
- "\tceq\n"
- "\tbrtrue\tL_02\n"
- "\tldloc\targs\n"
- "\tldloc\ti\n"
- "\tldelem.ref\n"
- "\tcall\tnative int [mscorlib]System.Runtime.InteropServices.Marshal::"
- "StringToHGlobalAnsi(string)\n"
- "\tstloc\tptr\n"
- "\tldloc\targv\n"
- "\tldloc\ti\n";
- printPtrLoad(TD->getPointerSize());
- Out <<
- "\tmul\n"
- "\tadd\n"
- "\tldloc\tptr\n"
- "\tstind.i\n"
- "\tldloc\ti\n"
- "\tldc.i4.1\n"
- "\tadd\n"
- "\tstloc\ti\n"
- "\tbr\tL_01\n"
- "L_02:\n"
- "\tcall void $MSIL_Init()\n";
-
- // Call user 'main' function.
- const Function* F = ModulePtr->getFunction("main");
- if (!F || F->isDeclaration()) {
- Out << "\tldc.i4.0\n\tret\n}\n";
- return;
- }
- bool BadSig = true;
- std::string Args("");
- Function::const_arg_iterator Arg1,Arg2;
-
- switch (F->arg_size()) {
- case 0:
- BadSig = false;
- break;
- case 1:
- Arg1 = F->arg_begin();
- if (Arg1->getType()->isIntegerTy()) {
- Out << "\tldloc\targc\n";
- Args = getTypeName(Arg1->getType());
- BadSig = false;
- }
- break;
- case 2:
- Arg1 = Arg2 = F->arg_begin(); ++Arg2;
- if (Arg1->getType()->isIntegerTy() &&
- Arg2->getType()->getTypeID() == Type::PointerTyID) {
- Out << "\tldloc\targc\n\tldloc\targv\n";
- Args = getTypeName(Arg1->getType())+","+getTypeName(Arg2->getType());
- BadSig = false;
- }
- break;
- default:
- BadSig = true;
- }
-
- bool RetVoid = (F->getReturnType()->getTypeID() == Type::VoidTyID);
- if (BadSig || (!F->getReturnType()->isIntegerTy() && !RetVoid)) {
- Out << "\tldc.i4.0\n";
- } else {
- Out << "\tcall\t" << getTypeName(F->getReturnType()) <<
- getConvModopt(F->getCallingConv()) << "main(" << Args << ")\n";
- if (RetVoid)
- Out << "\tldc.i4.0\n";
- else
- Out << "\tconv.i4\n";
- }
- Out << "\tret\n}\n";
-}
-
-bool MSILWriter::isZeroValue(const Value* V) {
- if (const Constant *C = dyn_cast<Constant>(V))
- return C->isNullValue();
- return false;
-}
-
-
-std::string MSILWriter::getValueName(const Value* V) {
- std::string Name;
- if (const GlobalValue *GV = dyn_cast<GlobalValue>(V))
- Name = GV->getName();
- else {
- unsigned &No = AnonValueNumbers[V];
- if (No == 0) No = ++NextAnonValueNumber;
- Name = "tmp" + utostr(No);
- }
-
- // Name into the quotes allow control and space characters.
- return "'"+Name+"'";
-}
-
-
-std::string MSILWriter::getLabelName(const std::string& Name) {
- if (Name.find('.')!=std::string::npos) {
- std::string Tmp(Name);
- // Replace unaccepable characters in the label name.
- for (std::string::iterator I = Tmp.begin(), E = Tmp.end(); I!=E; ++I)
- if (*I=='.') *I = '@';
- return Tmp;
- }
- return Name;
-}
-
-
-std::string MSILWriter::getLabelName(const Value* V) {
- std::string Name;
- if (const GlobalValue *GV = dyn_cast<GlobalValue>(V))
- Name = GV->getName();
- else {
- unsigned &No = AnonValueNumbers[V];
- if (No == 0) No = ++NextAnonValueNumber;
- Name = "tmp" + utostr(No);
- }
-
- return getLabelName(Name);
-}
-
-
-std::string MSILWriter::getConvModopt(CallingConv::ID CallingConvID) {
- switch (CallingConvID) {
- case CallingConv::C:
- case CallingConv::Cold:
- case CallingConv::Fast:
- return "modopt([mscorlib]System.Runtime.CompilerServices.CallConvCdecl) ";
- case CallingConv::X86_FastCall:
- return "modopt([mscorlib]System.Runtime.CompilerServices.CallConvFastcall) ";
- case CallingConv::X86_StdCall:
- return "modopt([mscorlib]System.Runtime.CompilerServices.CallConvStdcall) ";
- case CallingConv::X86_ThisCall:
- return "modopt([mscorlib]System.Runtime.CompilerServices.CallConvThiscall) ";
- default:
- errs() << "CallingConvID = " << CallingConvID << '\n';
- llvm_unreachable("Unsupported calling convention");
- }
- return ""; // Not reached
-}
-
-
-std::string MSILWriter::getArrayTypeName(Type::TypeID TyID, const Type* Ty) {
- std::string Tmp = "";
- const Type* ElemTy = Ty;
- assert(Ty->getTypeID()==TyID && "Invalid type passed");
- // Walk trought array element types.
- for (;;) {
- // Multidimensional array.
- if (ElemTy->getTypeID()==TyID) {
- if (const ArrayType* ATy = dyn_cast<ArrayType>(ElemTy))
- Tmp += utostr(ATy->getNumElements());
- else if (const VectorType* VTy = dyn_cast<VectorType>(ElemTy))
- Tmp += utostr(VTy->getNumElements());
- ElemTy = cast<SequentialType>(ElemTy)->getElementType();
- }
- // Base element type found.
- if (ElemTy->getTypeID()!=TyID) break;
- Tmp += ",";
- }
- return getTypeName(ElemTy, false, true)+"["+Tmp+"]";
-}
-
-
-std::string MSILWriter::getPrimitiveTypeName(const Type* Ty, bool isSigned) {
- unsigned NumBits = 0;
- switch (Ty->getTypeID()) {
- case Type::VoidTyID:
- return "void ";
- case Type::IntegerTyID:
- NumBits = getBitWidth(Ty);
- if(NumBits==1)
- return "bool ";
- if (!isSigned)
- return "unsigned int"+utostr(NumBits)+" ";
- return "int"+utostr(NumBits)+" ";
- case Type::FloatTyID:
- return "float32 ";
- case Type::DoubleTyID:
- return "float64 ";
- default:
- errs() << "Type = " << *Ty << '\n';
- llvm_unreachable("Invalid primitive type");
- }
- return ""; // Not reached
-}
-
-
-std::string MSILWriter::getTypeName(const Type* Ty, bool isSigned,
- bool isNested) {
- if (Ty->isPrimitiveType() || Ty->isIntegerTy())
- return getPrimitiveTypeName(Ty,isSigned);
- // FIXME: "OpaqueType" support
- switch (Ty->getTypeID()) {
- case Type::PointerTyID:
- return "void* ";
- case Type::StructTyID:
- if (isNested)
- return ModulePtr->getTypeName(Ty);
- return "valuetype '"+ModulePtr->getTypeName(Ty)+"' ";
- case Type::ArrayTyID:
- if (isNested)
- return getArrayTypeName(Ty->getTypeID(),Ty);
- return "valuetype '"+getArrayTypeName(Ty->getTypeID(),Ty)+"' ";
- case Type::VectorTyID:
- if (isNested)
- return getArrayTypeName(Ty->getTypeID(),Ty);
- return "valuetype '"+getArrayTypeName(Ty->getTypeID(),Ty)+"' ";
- default:
- errs() << "Type = " << *Ty << '\n';
- llvm_unreachable("Invalid type in getTypeName()");
- }
- return ""; // Not reached
-}
-
-
-MSILWriter::ValueType MSILWriter::getValueLocation(const Value* V) {
- // Function argument
- if (isa<Argument>(V))
- return ArgumentVT;
- // Function
- else if (const Function* F = dyn_cast<Function>(V))
- return F->hasLocalLinkage() ? InternalVT : GlobalVT;
- // Variable
- else if (const GlobalVariable* G = dyn_cast<GlobalVariable>(V))
- return G->hasLocalLinkage() ? InternalVT : GlobalVT;
- // Constant
- else if (isa<Constant>(V))
- return isa<ConstantExpr>(V) ? ConstExprVT : ConstVT;
- // Local variable
- return LocalVT;
-}
-
-
-std::string MSILWriter::getTypePostfix(const Type* Ty, bool Expand,
- bool isSigned) {
- unsigned NumBits = 0;
- switch (Ty->getTypeID()) {
- // Integer constant, expanding for stack operations.
- case Type::IntegerTyID:
- NumBits = getBitWidth(Ty);
- // Expand integer value to "int32" or "int64".
- if (Expand) return (NumBits<=32 ? "i4" : "i8");
- if (NumBits==1) return "i1";
- return (isSigned ? "i" : "u")+utostr(NumBits/8);
- // Float constant.
- case Type::FloatTyID:
- return "r4";
- case Type::DoubleTyID:
- return "r8";
- case Type::PointerTyID:
- return "i"+utostr(TD->getTypeAllocSize(Ty));
- default:
- errs() << "TypeID = " << Ty->getTypeID() << '\n';
- llvm_unreachable("Invalid type in TypeToPostfix()");
- }
- return ""; // Not reached
-}
-
-
-void MSILWriter::printConvToPtr() {
- switch (ModulePtr->getPointerSize()) {
- case Module::Pointer32:
- printSimpleInstruction("conv.u4");
- break;
- case Module::Pointer64:
- printSimpleInstruction("conv.u8");
- break;
- default:
- llvm_unreachable("Module use not supporting pointer size");
- }
-}
-
-
-void MSILWriter::printPtrLoad(uint64_t N) {
- switch (ModulePtr->getPointerSize()) {
- case Module::Pointer32:
- printSimpleInstruction("ldc.i4",utostr(N).c_str());
- // FIXME: Need overflow test?
- if (!isUInt<32>(N)) {
- errs() << "Value = " << utostr(N) << '\n';
- llvm_unreachable("32-bit pointer overflowed");
- }
- break;
- case Module::Pointer64:
- printSimpleInstruction("ldc.i8",utostr(N).c_str());
- break;
- default:
- llvm_unreachable("Module use not supporting pointer size");
- }
-}
-
-
-void MSILWriter::printValuePtrLoad(const Value* V) {
- printValueLoad(V);
- printConvToPtr();
-}
-
-
-void MSILWriter::printConstLoad(const Constant* C) {
- if (const ConstantInt* CInt = dyn_cast<ConstantInt>(C)) {
- // Integer constant
- Out << "\tldc." << getTypePostfix(C->getType(),true) << '\t';
- if (CInt->isMinValue(true))
- Out << CInt->getSExtValue();
- else
- Out << CInt->getZExtValue();
- } else if (const ConstantFP* FP = dyn_cast<ConstantFP>(C)) {
- // Float constant
- uint64_t X;
- unsigned Size;
- if (FP->getType()->getTypeID()==Type::FloatTyID) {
- X = (uint32_t)FP->getValueAPF().bitcastToAPInt().getZExtValue();
- Size = 4;
- } else {
- X = FP->getValueAPF().bitcastToAPInt().getZExtValue();
- Size = 8;
- }
- Out << "\tldc.r" << Size << "\t( " << utohexstr(X) << ')';
- } else if (isa<UndefValue>(C)) {
- // Undefined constant value = NULL.
- printPtrLoad(0);
- } else {
- errs() << "Constant = " << *C << '\n';
- llvm_unreachable("Invalid constant value");
- }
- Out << '\n';
-}
-
-
-void MSILWriter::printValueLoad(const Value* V) {
- MSILWriter::ValueType Location = getValueLocation(V);
- switch (Location) {
- // Global variable or function address.
- case GlobalVT:
- case InternalVT:
- if (const Function* F = dyn_cast<Function>(V)) {
- std::string Name = getConvModopt(F->getCallingConv())+getValueName(F);
- printSimpleInstruction("ldftn",
- getCallSignature(F->getFunctionType(),NULL,Name).c_str());
- } else {
- std::string Tmp;
- const Type* ElemTy = cast<PointerType>(V->getType())->getElementType();
- if (Location==GlobalVT && cast<GlobalVariable>(V)->hasDLLImportLinkage()) {
- Tmp = "void* "+getValueName(V);
- printSimpleInstruction("ldsfld",Tmp.c_str());
- } else {
- Tmp = getTypeName(ElemTy)+getValueName(V);
- printSimpleInstruction("ldsflda",Tmp.c_str());
- }
- }
- break;
- // Function argument.
- case ArgumentVT:
- printSimpleInstruction("ldarg",getValueName(V).c_str());
- break;
- // Local function variable.
- case LocalVT:
- printSimpleInstruction("ldloc",getValueName(V).c_str());
- break;
- // Constant value.
- case ConstVT:
- if (isa<ConstantPointerNull>(V))
- printPtrLoad(0);
- else
- printConstLoad(cast<Constant>(V));
- break;
- // Constant expression.
- case ConstExprVT:
- printConstantExpr(cast<ConstantExpr>(V));
- break;
- default:
- errs() << "Value = " << *V << '\n';
- llvm_unreachable("Invalid value location");
- }
-}
-
-
-void MSILWriter::printValueSave(const Value* V) {
- switch (getValueLocation(V)) {
- case ArgumentVT:
- printSimpleInstruction("starg",getValueName(V).c_str());
- break;
- case LocalVT:
- printSimpleInstruction("stloc",getValueName(V).c_str());
- break;
- default:
- errs() << "Value = " << *V << '\n';
- llvm_unreachable("Invalid value location");
- }
-}
-
-
-void MSILWriter::printBinaryInstruction(const char* Name, const Value* Left,
- const Value* Right) {
- printValueLoad(Left);
- printValueLoad(Right);
- Out << '\t' << Name << '\n';
-}
-
-
-void MSILWriter::printSimpleInstruction(const char* Inst, const char* Operand) {
- if(Operand)
- Out << '\t' << Inst << '\t' << Operand << '\n';
- else
- Out << '\t' << Inst << '\n';
-}
-
-
-void MSILWriter::printPHICopy(const BasicBlock* Src, const BasicBlock* Dst) {
- for (BasicBlock::const_iterator I = Dst->begin(); isa<PHINode>(I); ++I) {
- const PHINode* Phi = cast<PHINode>(I);
- const Value* Val = Phi->getIncomingValueForBlock(Src);
- if (isa<UndefValue>(Val)) continue;
- printValueLoad(Val);
- printValueSave(Phi);
- }
-}
-
-
-void MSILWriter::printBranchToBlock(const BasicBlock* CurrBB,
- const BasicBlock* TrueBB,
- const BasicBlock* FalseBB) {
- if (TrueBB==FalseBB) {
- // "TrueBB" and "FalseBB" destination equals
- printPHICopy(CurrBB,TrueBB);
- printSimpleInstruction("pop");
- printSimpleInstruction("br",getLabelName(TrueBB).c_str());
- } else if (FalseBB==NULL) {
- // If "FalseBB" not used the jump have condition
- printPHICopy(CurrBB,TrueBB);
- printSimpleInstruction("brtrue",getLabelName(TrueBB).c_str());
- } else if (TrueBB==NULL) {
- // If "TrueBB" not used the jump is unconditional
- printPHICopy(CurrBB,FalseBB);
- printSimpleInstruction("br",getLabelName(FalseBB).c_str());
- } else {
- // Copy PHI instructions for each block
- std::string TmpLabel;
- // Print PHI instructions for "TrueBB"
- if (isa<PHINode>(TrueBB->begin())) {
- TmpLabel = getLabelName(TrueBB)+"$phi_"+utostr(getUniqID());
- printSimpleInstruction("brtrue",TmpLabel.c_str());
- } else {
- printSimpleInstruction("brtrue",getLabelName(TrueBB).c_str());
- }
- // Print PHI instructions for "FalseBB"
- if (isa<PHINode>(FalseBB->begin())) {
- printPHICopy(CurrBB,FalseBB);
- printSimpleInstruction("br",getLabelName(FalseBB).c_str());
- } else {
- printSimpleInstruction("br",getLabelName(FalseBB).c_str());
- }
- if (isa<PHINode>(TrueBB->begin())) {
- // Handle "TrueBB" PHI Copy
- Out << TmpLabel << ":\n";
- printPHICopy(CurrBB,TrueBB);
- printSimpleInstruction("br",getLabelName(TrueBB).c_str());
- }
- }
-}
-
-
-void MSILWriter::printBranchInstruction(const BranchInst* Inst) {
- if (Inst->isUnconditional()) {
- printBranchToBlock(Inst->getParent(),NULL,Inst->getSuccessor(0));
- } else {
- printValueLoad(Inst->getCondition());
- printBranchToBlock(Inst->getParent(),Inst->getSuccessor(0),
- Inst->getSuccessor(1));
- }
-}
-
-
-void MSILWriter::printSelectInstruction(const Value* Cond, const Value* VTrue,
- const Value* VFalse) {
- std::string TmpLabel = std::string("select$true_")+utostr(getUniqID());
- printValueLoad(VTrue);
- printValueLoad(Cond);
- printSimpleInstruction("brtrue",TmpLabel.c_str());
- printSimpleInstruction("pop");
- printValueLoad(VFalse);
- Out << TmpLabel << ":\n";
-}
-
-
-void MSILWriter::printIndirectLoad(const Value* V) {
- const Type* Ty = V->getType();
- printValueLoad(V);
- if (const PointerType* P = dyn_cast<PointerType>(Ty))
- Ty = P->getElementType();
- std::string Tmp = "ldind."+getTypePostfix(Ty, false);
- printSimpleInstruction(Tmp.c_str());
-}
-
-
-void MSILWriter::printIndirectSave(const Value* Ptr, const Value* Val) {
- printValueLoad(Ptr);
- printValueLoad(Val);
- printIndirectSave(Val->getType());
-}
-
-
-void MSILWriter::printIndirectSave(const Type* Ty) {
- // Instruction need signed postfix for any type.
- std::string postfix = getTypePostfix(Ty, false);
- if (*postfix.begin()=='u') *postfix.begin() = 'i';
- postfix = "stind."+postfix;
- printSimpleInstruction(postfix.c_str());
-}
-
-
-void MSILWriter::printCastInstruction(unsigned int Op, const Value* V,
- const Type* Ty, const Type* SrcTy) {
- std::string Tmp("");
- printValueLoad(V);
- switch (Op) {
- // Signed
- case Instruction::SExt:
- // If sign extending int, convert first from unsigned to signed
- // with the same bit size - because otherwise we will loose the sign.
- if (SrcTy) {
- Tmp = "conv."+getTypePostfix(SrcTy,false,true);
- printSimpleInstruction(Tmp.c_str());
- }
- // FALLTHROUGH
- case Instruction::SIToFP:
- case Instruction::FPToSI:
- Tmp = "conv."+getTypePostfix(Ty,false,true);
- printSimpleInstruction(Tmp.c_str());
- break;
- // Unsigned
- case Instruction::FPTrunc:
- case Instruction::FPExt:
- case Instruction::UIToFP:
- case Instruction::Trunc:
- case Instruction::ZExt:
- case Instruction::FPToUI:
- case Instruction::PtrToInt:
- case Instruction::IntToPtr:
- Tmp = "conv."+getTypePostfix(Ty,false);
- printSimpleInstruction(Tmp.c_str());
- break;
- // Do nothing
- case Instruction::BitCast:
- // FIXME: meaning that ld*/st* instruction do not change data format.
- break;
- default:
- errs() << "Opcode = " << Op << '\n';
- llvm_unreachable("Invalid conversion instruction");
- }
-}
-
-
-void MSILWriter::printGepInstruction(const Value* V, gep_type_iterator I,
- gep_type_iterator E) {
- unsigned Size;
- // Load address
- printValuePtrLoad(V);
- // Calculate element offset.
- for (; I!=E; ++I){
- Size = 0;
- const Value* IndexValue = I.getOperand();
- if (const StructType* StrucTy = dyn_cast<StructType>(*I)) {
- uint64_t FieldIndex = cast<ConstantInt>(IndexValue)->getZExtValue();
- // Offset is the sum of all previous structure fields.
- for (uint64_t F = 0; F<FieldIndex; ++F)
- Size += TD->getTypeAllocSize(StrucTy->getContainedType((unsigned)F));
- printPtrLoad(Size);
- printSimpleInstruction("add");
- continue;
- } else if (const SequentialType* SeqTy = dyn_cast<SequentialType>(*I)) {
- Size = TD->getTypeAllocSize(SeqTy->getElementType());
- } else {
- Size = TD->getTypeAllocSize(*I);
- }
- // Add offset of current element to stack top.
- if (!isZeroValue(IndexValue)) {
- // Constant optimization.
- if (const ConstantInt* C = dyn_cast<ConstantInt>(IndexValue)) {
- if (C->getValue().isNegative()) {
- printPtrLoad(C->getValue().abs().getZExtValue()*Size);
- printSimpleInstruction("sub");
- continue;
- } else
- printPtrLoad(C->getZExtValue()*Size);
- } else {
- printPtrLoad(Size);
- printValuePtrLoad(IndexValue);
- printSimpleInstruction("mul");
- }
- printSimpleInstruction("add");
- }
- }
-}
-
-
-std::string MSILWriter::getCallSignature(const FunctionType* Ty,
- const Instruction* Inst,
- std::string Name) {
- std::string Tmp("");
- if (Ty->isVarArg()) Tmp += "vararg ";
- // Name and return type.
- Tmp += getTypeName(Ty->getReturnType())+Name+"(";
- // Function argument type list.
- unsigned NumParams = Ty->getNumParams();
- for (unsigned I = 0; I!=NumParams; ++I) {
- if (I!=0) Tmp += ",";
- Tmp += getTypeName(Ty->getParamType(I));
- }
- // CLR needs to know the exact amount of parameters received by vararg
- // function, because caller cleans the stack.
- if (Ty->isVarArg() && Inst) {
- // Origin to function arguments in "CallInst" or "InvokeInst".
- unsigned Org = isa<InvokeInst>(Inst) ? 3 : 1;
- // Print variable argument types.
- unsigned NumOperands = Inst->getNumOperands()-Org;
- if (NumParams<NumOperands) {
- if (NumParams!=0) Tmp += ", ";
- Tmp += "... , ";
- for (unsigned J = NumParams; J!=NumOperands; ++J) {
- if (J!=NumParams) Tmp += ", ";
- Tmp += getTypeName(Inst->getOperand(J+Org)->getType());
- }
- }
- }
- return Tmp+")";
-}
-
-
-void MSILWriter::printFunctionCall(const Value* FnVal,
- const Instruction* Inst) {
- // Get function calling convention.
- std::string Name = "";
- if (const CallInst* Call = dyn_cast<CallInst>(Inst))
- Name = getConvModopt(Call->getCallingConv());
- else if (const InvokeInst* Invoke = dyn_cast<InvokeInst>(Inst))
- Name = getConvModopt(Invoke->getCallingConv());
- else {
- errs() << "Instruction = " << Inst->getName() << '\n';
- llvm_unreachable("Need \"Invoke\" or \"Call\" instruction only");
- }
- if (const Function* F = dyn_cast<Function>(FnVal)) {
- // Direct call.
- Name += getValueName(F);
- printSimpleInstruction("call",
- getCallSignature(F->getFunctionType(),Inst,Name).c_str());
- } else {
- // Indirect function call.
- const PointerType* PTy = cast<PointerType>(FnVal->getType());
- const FunctionType* FTy = cast<FunctionType>(PTy->getElementType());
- // Load function address.
- printValueLoad(FnVal);
- printSimpleInstruction("calli",getCallSignature(FTy,Inst,Name).c_str());
- }
-}
-
-
-void MSILWriter::printIntrinsicCall(const IntrinsicInst* Inst) {
- std::string Name;
- switch (Inst->getIntrinsicID()) {
- case Intrinsic::vastart:
- Name = getValueName(Inst->getArgOperand(0));
- Name.insert(Name.length()-1,"$valist");
- // Obtain the argument handle.
- printSimpleInstruction("ldloca",Name.c_str());
- printSimpleInstruction("arglist");
- printSimpleInstruction("call",
- "instance void [mscorlib]System.ArgIterator::.ctor"
- "(valuetype [mscorlib]System.RuntimeArgumentHandle)");
- // Save as pointer type "void*"
- printValueLoad(Inst->getArgOperand(0));
- printSimpleInstruction("ldloca",Name.c_str());
- printIndirectSave(PointerType::getUnqual(
- IntegerType::get(Inst->getContext(), 8)));
- break;
- case Intrinsic::vaend:
- // Close argument list handle.
- printIndirectLoad(Inst->getArgOperand(0));
- printSimpleInstruction("call","instance void [mscorlib]System.ArgIterator::End()");
- break;
- case Intrinsic::vacopy:
- // Copy "ArgIterator" valuetype.
- printIndirectLoad(Inst->getArgOperand(0));
- printIndirectLoad(Inst->getArgOperand(1));
- printSimpleInstruction("cpobj","[mscorlib]System.ArgIterator");
- break;
- default:
- errs() << "Intrinsic ID = " << Inst->getIntrinsicID() << '\n';
- llvm_unreachable("Invalid intrinsic function");
- }
-}
-
-
-void MSILWriter::printCallInstruction(const Instruction* Inst) {
- if (isa<IntrinsicInst>(Inst)) {
- // Handle intrinsic function.
- printIntrinsicCall(cast<IntrinsicInst>(Inst));
- } else {
- const CallInst *CI = cast<CallInst>(Inst);
- // Load arguments to stack and call function.
- for (int I = 0, E = CI->getNumArgOperands(); I!=E; ++I)
- printValueLoad(CI->getArgOperand(I));
- printFunctionCall(CI->getCalledFunction(), Inst);
- }
-}
-
-
-void MSILWriter::printICmpInstruction(unsigned Predicate, const Value* Left,
- const Value* Right) {
- switch (Predicate) {
- case ICmpInst::ICMP_EQ:
- printBinaryInstruction("ceq",Left,Right);
- break;
- case ICmpInst::ICMP_NE:
- // Emulate = not neg (Op1 eq Op2)
- printBinaryInstruction("ceq",Left,Right);
- printSimpleInstruction("neg");
- printSimpleInstruction("not");
- break;
- case ICmpInst::ICMP_ULE:
- case ICmpInst::ICMP_SLE:
- // Emulate = (Op1 eq Op2) or (Op1 lt Op2)
- printBinaryInstruction("ceq",Left,Right);
- if (Predicate==ICmpInst::ICMP_ULE)
- printBinaryInstruction("clt.un",Left,Right);
- else
- printBinaryInstruction("clt",Left,Right);
- printSimpleInstruction("or");
- break;
- case ICmpInst::ICMP_UGE:
- case ICmpInst::ICMP_SGE:
- // Emulate = (Op1 eq Op2) or (Op1 gt Op2)
- printBinaryInstruction("ceq",Left,Right);
- if (Predicate==ICmpInst::ICMP_UGE)
- printBinaryInstruction("cgt.un",Left,Right);
- else
- printBinaryInstruction("cgt",Left,Right);
- printSimpleInstruction("or");
- break;
- case ICmpInst::ICMP_ULT:
- printBinaryInstruction("clt.un",Left,Right);
- break;
- case ICmpInst::ICMP_SLT:
- printBinaryInstruction("clt",Left,Right);
- break;
- case ICmpInst::ICMP_UGT:
- printBinaryInstruction("cgt.un",Left,Right);
- break;
- case ICmpInst::ICMP_SGT:
- printBinaryInstruction("cgt",Left,Right);
- break;
- default:
- errs() << "Predicate = " << Predicate << '\n';
- llvm_unreachable("Invalid icmp predicate");
- }
-}
-
-
-void MSILWriter::printFCmpInstruction(unsigned Predicate, const Value* Left,
- const Value* Right) {
- // FIXME: Correct comparison
- std::string NanFunc = "bool [mscorlib]System.Double::IsNaN(float64)";
- switch (Predicate) {
- case FCmpInst::FCMP_UGT:
- // X > Y || llvm_fcmp_uno(X, Y)
- printBinaryInstruction("cgt",Left,Right);
- printFCmpInstruction(FCmpInst::FCMP_UNO,Left,Right);
- printSimpleInstruction("or");
- break;
- case FCmpInst::FCMP_OGT:
- // X > Y
- printBinaryInstruction("cgt",Left,Right);
- break;
- case FCmpInst::FCMP_UGE:
- // X >= Y || llvm_fcmp_uno(X, Y)
- printBinaryInstruction("ceq",Left,Right);
- printBinaryInstruction("cgt",Left,Right);
- printSimpleInstruction("or");
- printFCmpInstruction(FCmpInst::FCMP_UNO,Left,Right);
- printSimpleInstruction("or");
- break;
- case FCmpInst::FCMP_OGE:
- // X >= Y
- printBinaryInstruction("ceq",Left,Right);
- printBinaryInstruction("cgt",Left,Right);
- printSimpleInstruction("or");
- break;
- case FCmpInst::FCMP_ULT:
- // X < Y || llvm_fcmp_uno(X, Y)
- printBinaryInstruction("clt",Left,Right);
- printFCmpInstruction(FCmpInst::FCMP_UNO,Left,Right);
- printSimpleInstruction("or");
- break;
- case FCmpInst::FCMP_OLT:
- // X < Y
- printBinaryInstruction("clt",Left,Right);
- break;
- case FCmpInst::FCMP_ULE:
- // X <= Y || llvm_fcmp_uno(X, Y)
- printBinaryInstruction("ceq",Left,Right);
- printBinaryInstruction("clt",Left,Right);
- printSimpleInstruction("or");
- printFCmpInstruction(FCmpInst::FCMP_UNO,Left,Right);
- printSimpleInstruction("or");
- break;
- case FCmpInst::FCMP_OLE:
- // X <= Y
- printBinaryInstruction("ceq",Left,Right);
- printBinaryInstruction("clt",Left,Right);
- printSimpleInstruction("or");
- break;
- case FCmpInst::FCMP_UEQ:
- // X == Y || llvm_fcmp_uno(X, Y)
- printBinaryInstruction("ceq",Left,Right);
- printFCmpInstruction(FCmpInst::FCMP_UNO,Left,Right);
- printSimpleInstruction("or");
- break;
- case FCmpInst::FCMP_OEQ:
- // X == Y
- printBinaryInstruction("ceq",Left,Right);
- break;
- case FCmpInst::FCMP_UNE:
- // X != Y
- printBinaryInstruction("ceq",Left,Right);
- printSimpleInstruction("neg");
- printSimpleInstruction("not");
- break;
- case FCmpInst::FCMP_ONE:
- // X != Y && llvm_fcmp_ord(X, Y)
- printBinaryInstruction("ceq",Left,Right);
- printSimpleInstruction("not");
- break;
- case FCmpInst::FCMP_ORD:
- // return X == X && Y == Y
- printBinaryInstruction("ceq",Left,Left);
- printBinaryInstruction("ceq",Right,Right);
- printSimpleInstruction("or");
- break;
- case FCmpInst::FCMP_UNO:
- // X != X || Y != Y
- printBinaryInstruction("ceq",Left,Left);
- printSimpleInstruction("not");
- printBinaryInstruction("ceq",Right,Right);
- printSimpleInstruction("not");
- printSimpleInstruction("or");
- break;
- default:
- llvm_unreachable("Illegal FCmp predicate");
- }
-}
-
-
-void MSILWriter::printInvokeInstruction(const InvokeInst* Inst) {
- std::string Label = "leave$normal_"+utostr(getUniqID());
- Out << ".try {\n";
- // Load arguments
- for (int I = 0, E = Inst->getNumArgOperands(); I!=E; ++I)
- printValueLoad(Inst->getArgOperand(I));
- // Print call instruction
- printFunctionCall(Inst->getOperand(0),Inst);
- // Save function result and leave "try" block
- printValueSave(Inst);
- printSimpleInstruction("leave",Label.c_str());
- Out << "}\n";
- Out << "catch [mscorlib]System.Exception {\n";
- // Redirect to unwind block
- printSimpleInstruction("pop");
- printBranchToBlock(Inst->getParent(),NULL,Inst->getUnwindDest());
- Out << "}\n" << Label << ":\n";
- // Redirect to continue block
- printBranchToBlock(Inst->getParent(),NULL,Inst->getNormalDest());
-}
-
-
-void MSILWriter::printSwitchInstruction(const SwitchInst* Inst) {
- // FIXME: Emulate with IL "switch" instruction
- // Emulate = if () else if () else if () else ...
- for (unsigned int I = 1, E = Inst->getNumCases(); I!=E; ++I) {
- printValueLoad(Inst->getCondition());
- printValueLoad(Inst->getCaseValue(I));
- printSimpleInstruction("ceq");
- // Condition jump to successor block
- printBranchToBlock(Inst->getParent(),Inst->getSuccessor(I),NULL);
- }
- // Jump to default block
- printBranchToBlock(Inst->getParent(),NULL,Inst->getDefaultDest());
-}
-
-
-void MSILWriter::printVAArgInstruction(const VAArgInst* Inst) {
- printIndirectLoad(Inst->getOperand(0));
- printSimpleInstruction("call",
- "instance typedref [mscorlib]System.ArgIterator::GetNextArg()");
- printSimpleInstruction("refanyval","void*");
- std::string Name =
- "ldind."+getTypePostfix(PointerType::getUnqual(
- IntegerType::get(I