Mercurial > projects > dang
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 |