comparison gen/CodeGen.d @ 120:7d0898f77685

Implement the cast expression - works for integers and real/float/double
author Anders Halager <halager@gmail.com>
date Sun, 25 May 2008 20:18:55 +0200
parents c0b531362ca6
children 95dfe2f48dcf
comparison
equal deleted inserted replaced
119:c0b531362ca6 120:7d0898f77685
355 // BUG: doesn't do implicit type-conversion on args 355 // BUG: doesn't do implicit type-conversion on args
356 auto r = b.buildCall(f, args, isVoid? "" : "call"); 356 auto r = b.buildCall(f, args, isVoid? "" : "call");
357 return RValue(r); 357 return RValue(r);
358 case ExpType.CastExp: 358 case ExpType.CastExp:
359 auto castExp = cast(CastExp)exp; 359 auto castExp = cast(CastExp)exp;
360 auto value = genExpression(castExp.exp).value; 360 exp = castExp.exp;
361 361 auto value = genExpression(exp);
362 if (!castExp.exp.type.hasImplicitConversionTo(castExp.type)) 362
363 if (!exp.type.hasImplicitConversionTo(castExp.type))
363 assert(0, "Invalid cast"); 364 assert(0, "Invalid cast");
364 365
365 Value v = buildCastLoad(castExp.exp.type, castExp.type, value); 366 return genTypeCast(value, exp.type, castExp.type);
366
367 return RValue(v);
368 367
369 case ExpType.Identifier: 368 case ExpType.Identifier:
370 auto identifier = cast(Identifier)exp; 369 auto identifier = cast(Identifier)exp;
371 auto id = exp.env.find(identifier); 370 auto id = exp.env.find(identifier);
372 if(id.type.isStruct() || id.type.isArray()) 371 if(id.type.isStruct() || id.type.isArray())
398 // TODO: support floats 397 // TODO: support floats
399 if (t_a.isArithmetic() && t_b.isArithmetic()) 398 if (t_a.isArithmetic() && t_b.isArithmetic())
400 { 399 {
401 Operation op = t_a.getOperationWith(op2op(e.op), t_b); 400 Operation op = t_a.getOperationWith(op2op(e.op), t_b);
402 assert(op.isBuiltin(), 401 assert(op.isBuiltin(),
403 "integers should only use builtin ops"); 402 "numbers should only use builtin ops");
404 alias BuiltinOperation BO; 403 alias BuiltinOperation BO;
405 BO val = op.builtinOp(); 404 BO val = op.builtinOp();
406 // map val to buildAdd or similar 405 // map val to buildAdd or similar
407 switch (val) { 406 switch (val) {
408 case BO.Add: res = b.buildAdd(left, right, "add"); break; 407 case BO.Add: res = b.buildAdd(left, right, "add"); break;
606 } 605 }
607 } 606 }
608 b.positionAtEnd(endBB); 607 b.positionAtEnd(endBB);
609 break; 608 break;
610 } 609 }
611 }
612
613 /**
614 Given the address of something, load it into an alloc.
615 **/
616 RValue loadLValue(LValue addr, char[] name = null)
617 {
618 Value val = addr.getAddress();
619 if (name is null)
620 name = val.name.length > 0? val.name : "load";
621
622 auto res = b.buildLoad(val, name);
623 return RValue(res);
624 } 610 }
625 611
626 /* 612 /*
627 Get the address of an expression - allowing us to modify something in 613 Get the address of an expression - allowing us to modify something in
628 memory or on the stack. 614 memory or on the stack.
733 args[3] = ConstantInt.GetS(Type.Int32, 32); 719 args[3] = ConstantInt.GetS(Type.Int32, 32);
734 b.buildCall(llvm_memcpy, args[], null); 720 b.buildCall(llvm_memcpy, args[], null);
735 } 721 }
736 722
737 /** 723 /**
724 Generate the statements necessary to convert V, from type 'from' to type
725 'to'.
726 **/
727 RValue genTypeCast(RValue V, DType from, DType to)
728 {
729 Value delegate(Value, Type, char[]) extend, trunc;
730 if(auto ito = to.asInteger())
731 {
732 extend = ito.unsigned? &b.buildZExt : &b.buildSExt;
733 trunc = &b.buildTrunc;
734 if(auto rfrom = from.isReal())
735 {
736 extend = ito.unsigned? &b.buildFPToUI : &b.buildFPToSI;
737 trunc = extend;
738 }
739 }
740 else if (auto rto = to.asReal())
741 {
742 extend = &b.buildFPExt;
743 trunc = &b.buildFPTrunc;
744 if(auto ifrom = from.isInteger())
745 {
746 extend = rto.unsigned? &b.buildUIToFP : &b.buildSIToFP;
747 trunc = extend;
748 }
749 }
750 else
751 assert(0, "implicit cast need implimentation");
752
753 Value res;
754 if (from.byteSize() < to.byteSize())
755 res = extend(V.value, llvm(to), "ext");
756 else
757 res = trunc(V.value, llvm(to), "trunc");
758 return RValue(res);
759 }
760
761 /**
762 Given the address of something, load it into an alloc.
763 **/
764 RValue loadLValue(LValue addr, char[] name = null)
765 {
766 Value val = addr.getAddress();
767 if (name is null)
768 name = val.name.length > 0? val.name : "load";
769
770 auto res = b.buildLoad(val, name);
771 return RValue(res);
772 }
773
774 /**
738 Get the LLVM Type corresponding to a DType. 775 Get the LLVM Type corresponding to a DType.
739 776
740 Currently using the built-in associative array - not sure if it works 777 Currently using the built-in associative array - not sure if it works
741 well when the hashes are so uniform. 778 well when the hashes are so uniform.
742 779
828 return res; 865 return res;
829 } 866 }
830 assert(0, "Only integers, structs and functions are supported"); 867 assert(0, "Only integers, structs and functions are supported");
831 } 868 }
832 869
833 Value buildCastLoad(DType from, DType to, Value value)
834 {
835 if(typeof(from) == DInteger)
836 {
837 if(to == Type.Double)
838 return b.buildFPTrunc(value, llvm(_to), "fptrunc");
839 if(to == Type.Float)
840 return b.buildFPTrunc(value, llvm(_to), "fptrunc");
841 }
842 /*
843 if(from == Type.Int64)
844 if(castExp.exp.type.byteSize <= castExp.type.byteSize)
845 v = b.buildZExt(value, llvm(castExp.type), "zext");
846 else
847 v = b.buildTrunc(value, llvm(castExp.type), "trunc");
848 }
849 */
850 assert(0, "implicit cast need implimentation");
851 }
852 // Might as well insert all the basic types from the start 870 // Might as well insert all the basic types from the start
853 void createBasicTypes() 871 void createBasicTypes()
854 { 872 {
855 type_map[DType.Void] = Type.Void; 873 type_map[DType.Void] = Type.Void;
856 874