1 // Copyright 2014 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef V8_COMPILER_REPRESENTATION_CHANGE_H_ 6 #define V8_COMPILER_REPRESENTATION_CHANGE_H_ 7 8 #include "src/compiler/js-graph.h" 9 #include "src/compiler/simplified-operator.h" 10 11 namespace v8 { 12 namespace internal { 13 namespace compiler { 14 15 class Truncation final { 16 public: 17 // Constructors. 18 static Truncation None() { return Truncation(TruncationKind::kNone); } 19 static Truncation Bool() { return Truncation(TruncationKind::kBool); } 20 static Truncation Word32() { return Truncation(TruncationKind::kWord32); } 21 static Truncation Word64() { return Truncation(TruncationKind::kWord64); } 22 static Truncation Float32() { return Truncation(TruncationKind::kFloat32); } 23 static Truncation Float64() { return Truncation(TruncationKind::kFloat64); } 24 static Truncation Any() { return Truncation(TruncationKind::kAny); } 25 26 static Truncation Generalize(Truncation t1, Truncation t2) { 27 return Truncation(Generalize(t1.kind(), t2.kind())); 28 } 29 30 // Queries. 31 bool TruncatesToWord32() const { 32 return LessGeneral(kind_, TruncationKind::kWord32); 33 } 34 bool TruncatesNaNToZero() { 35 return LessGeneral(kind_, TruncationKind::kWord32) || 36 LessGeneral(kind_, TruncationKind::kBool); 37 } 38 bool TruncatesUndefinedToZeroOrNaN() { 39 return LessGeneral(kind_, TruncationKind::kFloat64) || 40 LessGeneral(kind_, TruncationKind::kWord64); 41 } 42 43 // Operators. 44 bool operator==(Truncation other) const { return kind() == other.kind(); } 45 bool operator!=(Truncation other) const { return !(*this == other); } 46 47 // Debug utilities. 48 const char* description() const; 49 bool IsLessGeneralThan(Truncation other) { 50 return LessGeneral(kind(), other.kind()); 51 } 52 53 private: 54 enum class TruncationKind : uint8_t { 55 kNone, 56 kBool, 57 kWord32, 58 kWord64, 59 kFloat32, 60 kFloat64, 61 kAny 62 }; 63 64 explicit Truncation(TruncationKind kind) : kind_(kind) {} 65 TruncationKind kind() const { return kind_; } 66 67 TruncationKind kind_; 68 69 static TruncationKind Generalize(TruncationKind rep1, TruncationKind rep2); 70 static bool LessGeneral(TruncationKind rep1, TruncationKind rep2); 71 }; 72 73 74 // Contains logic related to changing the representation of values for constants 75 // and other nodes, as well as lowering Simplified->Machine operators. 76 // Eagerly folds any representation changes for constants. 77 class RepresentationChanger final { 78 public: 79 RepresentationChanger(JSGraph* jsgraph, Isolate* isolate) 80 : jsgraph_(jsgraph), 81 isolate_(isolate), 82 testing_type_errors_(false), 83 type_error_(false) {} 84 85 // Changes representation from {output_type} to {use_rep}. The {truncation} 86 // parameter is only used for sanity checking - if the changer cannot figure 87 // out signedness for the word32->float64 conversion, then we check that the 88 // uses truncate to word32 (so they do not care about signedness). 89 Node* GetRepresentationFor(Node* node, MachineRepresentation output_rep, 90 Type* output_type, MachineRepresentation use_rep, 91 Truncation truncation = Truncation::None()); 92 const Operator* Int32OperatorFor(IrOpcode::Value opcode); 93 const Operator* Uint32OperatorFor(IrOpcode::Value opcode); 94 const Operator* Float64OperatorFor(IrOpcode::Value opcode); 95 96 MachineType TypeForBasePointer(const FieldAccess& access) { 97 return access.tag() != 0 ? MachineType::AnyTagged() 98 : MachineType::Pointer(); 99 } 100 101 MachineType TypeForBasePointer(const ElementAccess& access) { 102 return access.tag() != 0 ? MachineType::AnyTagged() 103 : MachineType::Pointer(); 104 } 105 106 private: 107 JSGraph* jsgraph_; 108 Isolate* isolate_; 109 110 friend class RepresentationChangerTester; // accesses the below fields. 111 112 bool testing_type_errors_; // If {true}, don't abort on a type error. 113 bool type_error_; // Set when a type error is detected. 114 115 Node* GetTaggedRepresentationFor(Node* node, MachineRepresentation output_rep, 116 Type* output_type); 117 Node* GetFloat32RepresentationFor(Node* node, 118 MachineRepresentation output_rep, 119 Type* output_type, Truncation truncation); 120 Node* GetFloat64RepresentationFor(Node* node, 121 MachineRepresentation output_rep, 122 Type* output_type, Truncation truncation); 123 Node* GetWord32RepresentationFor(Node* node, MachineRepresentation output_rep, 124 Type* output_type); 125 Node* GetBitRepresentationFor(Node* node, MachineRepresentation output_rep, 126 Type* output_type); 127 Node* GetWord64RepresentationFor(Node* node, MachineRepresentation output_rep, 128 Type* output_type); 129 Node* TypeError(Node* node, MachineRepresentation output_rep, 130 Type* output_type, MachineRepresentation use); 131 Node* MakeTruncatedInt32Constant(double value); 132 Node* InsertChangeFloat32ToFloat64(Node* node); 133 Node* InsertChangeTaggedToFloat64(Node* node); 134 135 JSGraph* jsgraph() const { return jsgraph_; } 136 Isolate* isolate() const { return isolate_; } 137 Factory* factory() const { return isolate()->factory(); } 138 SimplifiedOperatorBuilder* simplified() { return jsgraph()->simplified(); } 139 MachineOperatorBuilder* machine() { return jsgraph()->machine(); } 140 }; 141 142 } // namespace compiler 143 } // namespace internal 144 } // namespace v8 145 146 #endif // V8_COMPILER_REPRESENTATION_CHANGE_H_ 147