diff gen/tollvm.cpp @ 97:c4e161556a21 trunk

[svn r101] Split up CastExp into several smaller utility functions.
author lindquist
date Wed, 14 Nov 2007 20:18:01 +0100
parents ce7ed8f59b99
children 6789050b5ad1
line wrap: on
line diff
--- a/gen/tollvm.cpp	Mon Nov 12 07:58:44 2007 +0100
+++ b/gen/tollvm.cpp	Wed Nov 14 20:18:01 2007 +0100
@@ -1305,6 +1305,234 @@
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
+DValue* DtoCastInt(DValue* val, Type* _to)
+{
+    const llvm::Type* tolltype = DtoType(_to);
+
+    Type* to = DtoDType(_to);
+    Type* from = DtoDType(val->getType());
+    assert(from->isintegral());
+
+    size_t fromsz = from->size();
+    size_t tosz = to->size();
+
+    llvm::Value* rval;
+
+    if (to->isintegral()) {
+        if (fromsz < tosz) {
+            Logger::cout() << "cast to: " << *tolltype << '\n';
+            if (from->isunsigned() || from->ty == Tbool) {
+                rval = new llvm::ZExtInst(val->getRVal(), tolltype, "tmp", gIR->scopebb());
+            } else {
+                rval = new llvm::SExtInst(val->getRVal(), tolltype, "tmp", gIR->scopebb());
+            }
+        }
+        else if (fromsz > tosz) {
+            rval = new llvm::TruncInst(val->getRVal(), tolltype, "tmp", gIR->scopebb());
+        }
+        else {
+            rval = new llvm::BitCastInst(val->getRVal(), tolltype, "tmp", gIR->scopebb());
+        }
+    }
+    else if (to->isfloating()) {
+        if (from->isunsigned()) {
+            rval = new llvm::UIToFPInst(val->getRVal(), tolltype, "tmp", gIR->scopebb());
+        }
+        else {
+            rval = new llvm::SIToFPInst(val->getRVal(), tolltype, "tmp", gIR->scopebb());
+        }
+    }
+    else if (to->ty == Tpointer) {
+        rval = gIR->ir->CreateIntToPtr(val->getRVal(), tolltype, "tmp");
+    }
+    else {
+        assert(0 && "bad int cast");
+    }
+
+    return new DImValue(_to, rval);
+}
+
+DValue* DtoCastPtr(DValue* val, Type* to)
+{
+    const llvm::Type* tolltype = DtoType(to);
+
+    Type* totype = DtoDType(to);
+    Type* fromtype = DtoDType(val->getType());
+    assert(fromtype->ty == Tpointer);
+
+    llvm::Value* rval;
+
+    if (totype->ty == Tpointer || totype->ty == Tclass) {
+        llvm::Value* src = val->getRVal();
+        Logger::cout() << "src: " << *src << "to type: " << *tolltype << '\n';
+        rval = new llvm::BitCastInst(src, tolltype, "tmp", gIR->scopebb());
+    }
+    else if (totype->isintegral()) {
+        rval = new llvm::PtrToIntInst(val->getRVal(), tolltype, "tmp", gIR->scopebb());
+    }
+    else {
+        assert(0);
+    }
+
+    return new DImValue(to, rval);
+}
+
+DValue* DtoCastFloat(DValue* val, Type* to)
+{
+    const llvm::Type* tolltype = DtoType(to);
+
+    Type* totype = DtoDType(to);
+    Type* fromtype = DtoDType(val->getType());
+    assert(fromtype->isfloating());
+
+    size_t fromsz = fromtype->size();
+    size_t tosz = totype->size();
+
+    llvm::Value* rval;
+
+    if (totype->isfloating()) {
+        if ((fromtype->ty == Tfloat80 || fromtype->ty == Tfloat64) && (totype->ty == Tfloat80 || totype->ty == Tfloat64)) {
+            rval = val->getRVal();
+        }
+        else if (fromsz < tosz) {
+            rval = new llvm::FPExtInst(val->getRVal(), tolltype, "tmp", gIR->scopebb());
+        }
+        else if (fromsz > tosz) {
+            rval = new llvm::FPTruncInst(val->getRVal(), tolltype, "tmp", gIR->scopebb());
+        }
+        else {
+            assert(0 && "bad float cast");
+        }
+    }
+    else if (totype->isintegral()) {
+        if (totype->isunsigned()) {
+            rval = new llvm::FPToUIInst(val->getRVal(), tolltype, "tmp", gIR->scopebb());
+        }
+        else {
+            rval = new llvm::FPToSIInst(val->getRVal(), tolltype, "tmp", gIR->scopebb());
+        }
+    }
+    else {
+        assert(0 && "bad float cast");
+    }
+
+    return new DImValue(to, rval);
+}
+
+DValue* DtoCastClass(DValue* val, Type* _to)
+{
+    const llvm::Type* tolltype = DtoType(_to);
+    Type* to = DtoDType(_to);
+    assert(to->ty == Tclass);
+    llvm::Value* rval = new llvm::BitCastInst(val->getRVal(), tolltype, "tmp", gIR->scopebb());
+    return new DImValue(_to, rval);
+}
+
+DValue* DtoCastArray(DValue* u, Type* to)
+{
+    const llvm::Type* tolltype = DtoType(to);
+
+    Type* totype = DtoDType(to);
+    Type* fromtype = DtoDType(u->getType());
+    assert(fromtype->ty == Tarray || fromtype->ty == Tsarray);
+
+    llvm::Value* rval;
+    llvm::Value* rval2;
+    bool isslice = false;
+
+    Logger::cout() << "from array or sarray" << '\n';
+    if (totype->ty == Tpointer) {
+        Logger::cout() << "to pointer" << '\n';
+        assert(fromtype->next == totype->next || totype->next->ty == Tvoid);
+        llvm::Value* ptr = DtoGEPi(u->getRVal(),0,1,"tmp",gIR->scopebb());
+        rval = new llvm::LoadInst(ptr, "tmp", gIR->scopebb());
+        if (fromtype->next != totype->next)
+            rval = gIR->ir->CreateBitCast(rval, llvm::PointerType::get(llvm::Type::Int8Ty), "tmp");
+    }
+    else if (totype->ty == Tarray) {
+        Logger::cout() << "to array" << '\n';
+        const llvm::Type* ptrty = DtoType(totype->next);
+        if (ptrty == llvm::Type::VoidTy)
+            ptrty = llvm::Type::Int8Ty;
+        ptrty = llvm::PointerType::get(ptrty);
+
+        const llvm::Type* ety = DtoType(fromtype->next);
+        if (ety == llvm::Type::VoidTy)
+            ety = llvm::Type::Int8Ty;
+
+        if (DSliceValue* usl = u->isSlice()) {
+            Logger::println("from slice");
+            rval = new llvm::BitCastInst(usl->ptr, ptrty, "tmp", gIR->scopebb());
+            if (fromtype->next->size() == totype->next->size())
+                rval2 = usl->len;
+            else
+                rval2 = DtoArrayCastLength(usl->len, ety, ptrty->getContainedType(0));
+        }
+        else {
+            llvm::Value* uval = u->getRVal();
+            if (fromtype->ty == Tsarray) {
+                Logger::cout() << "uvalTy = " << *uval->getType() << '\n';
+                assert(isaPointer(uval->getType()));
+                const llvm::ArrayType* arrty = isaArray(uval->getType()->getContainedType(0));
+                rval2 = llvm::ConstantInt::get(DtoSize_t(), arrty->getNumElements(), false);
+                rval2 = DtoArrayCastLength(rval2, ety, ptrty->getContainedType(0));
+                rval = new llvm::BitCastInst(uval, ptrty, "tmp", gIR->scopebb());
+            }
+            else {
+                llvm::Value* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
+                llvm::Value* one = llvm::ConstantInt::get(llvm::Type::Int32Ty, 1, false);
+                rval2 = DtoGEP(uval,zero,zero,"tmp",gIR->scopebb());
+                rval2 = new llvm::LoadInst(rval2, "tmp", gIR->scopebb());
+                rval2 = DtoArrayCastLength(rval2, ety, ptrty->getContainedType(0));
+
+                rval = DtoGEP(uval,zero,one,"tmp",gIR->scopebb());
+                rval = new llvm::LoadInst(rval, "tmp", gIR->scopebb());
+                //Logger::cout() << *e->mem->getType() << '|' << *ptrty << '\n';
+                rval = new llvm::BitCastInst(rval, ptrty, "tmp", gIR->scopebb());
+            }
+        }
+        isslice = true;
+    }
+    else if (totype->ty == Tsarray) {
+        Logger::cout() << "to sarray" << '\n';
+        assert(0);
+    }
+    else {
+        assert(0);
+    }
+
+    if (isslice) {
+        Logger::println("isslice");
+        return new DSliceValue(to, rval2, rval);
+    }
+
+    return new DImValue(to, rval);
+}
+
+DValue* DtoCast(DValue* val, Type* to)
+{
+    Type* fromtype = DtoDType(val->getType());
+    if (fromtype->isintegral()) {
+        return DtoCastInt(val, to);
+    }
+    else if (fromtype->isfloating()) {
+        return DtoCastFloat(val, to);
+    }
+    else if (fromtype->ty == Tclass) {
+        return DtoCastClass(val, to);
+    }
+    else if (fromtype->ty == Tarray || fromtype->ty == Tsarray) {
+        return DtoCastArray(val, to);
+    }
+    else if (fromtype->ty == Tpointer) {
+        return DtoCastPtr(val, to);
+    }
+    else {
+        assert(0);
+    }
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
 
 llvm::ConstantInt* DtoConstSize_t(size_t i)
 {