#ifndef V8_COMPILER_REPRESENTATION_CHANGE_H_
#define V8_COMPILER_REPRESENTATION_CHANGE_H_
+#include <sstream>
+
#include "src/base/bits.h"
#include "src/compiler/js-graph.h"
#include "src/compiler/machine-operator.h"
}
if (use_type & kRepTagged) {
return GetTaggedRepresentationFor(node, output_type);
+ } else if (use_type & kRepFloat32) {
+ return GetFloat32RepresentationFor(node, output_type);
} else if (use_type & kRepFloat64) {
return GetFloat64RepresentationFor(node, output_type);
- } else if (use_type & kRepFloat32) {
- return TypeError(node, output_type, use_type); // TODO(titzer): handle
} else if (use_type & kRepBit) {
return GetBitRepresentationFor(node, output_type);
} else if (use_type & rWord) {
}
case IrOpcode::kFloat64Constant:
return jsgraph()->Constant(OpParameter<double>(node));
+ case IrOpcode::kFloat32Constant:
+ return jsgraph()->Constant(OpParameter<float>(node));
default:
break;
}
} else {
return TypeError(node, output_type, kRepTagged);
}
+ } else if (output_type & kRepFloat32) { // float32 -> float64 -> tagged
+ node = InsertChangeFloat32ToFloat64(node);
+ op = simplified()->ChangeFloat64ToTagged();
} else if (output_type & kRepFloat64) {
op = simplified()->ChangeFloat64ToTagged();
} else {
return jsgraph()->graph()->NewNode(op, node);
}
+ Node* GetFloat32RepresentationFor(Node* node, MachineTypeUnion output_type) {
+ // Eagerly fold representation changes for constants.
+ switch (node->opcode()) {
+ case IrOpcode::kFloat64Constant:
+ case IrOpcode::kNumberConstant:
+ return jsgraph()->Float32Constant(
+ DoubleToFloat32(OpParameter<double>(node)));
+ case IrOpcode::kInt32Constant:
+ if (output_type & kTypeUint32) {
+ uint32_t value = OpParameter<uint32_t>(node);
+ return jsgraph()->Float32Constant(static_cast<float>(value));
+ } else {
+ int32_t value = OpParameter<int32_t>(node);
+ return jsgraph()->Float32Constant(static_cast<float>(value));
+ }
+ case IrOpcode::kFloat32Constant:
+ return node; // No change necessary.
+ default:
+ break;
+ }
+ // Select the correct X -> Float32 operator.
+ const Operator* op;
+ if (output_type & kRepBit) {
+ return TypeError(node, output_type, kRepFloat32);
+ } else if (output_type & rWord) {
+ if (output_type & kTypeUint32) {
+ op = machine()->ChangeUint32ToFloat64();
+ } else {
+ op = machine()->ChangeInt32ToFloat64();
+ }
+ // int32 -> float64 -> float32
+ node = jsgraph()->graph()->NewNode(op, node);
+ op = machine()->TruncateFloat64ToFloat32();
+ } else if (output_type & kRepTagged) {
+ op = simplified()
+ ->ChangeTaggedToFloat64(); // tagged -> float64 -> float32
+ node = jsgraph()->graph()->NewNode(op, node);
+ op = machine()->TruncateFloat64ToFloat32();
+ } else if (output_type & kRepFloat64) {
+ op = machine()->TruncateFloat64ToFloat32();
+ } else {
+ return TypeError(node, output_type, kRepFloat32);
+ }
+ return jsgraph()->graph()->NewNode(op, node);
+ }
+
Node* GetFloat64RepresentationFor(Node* node, MachineTypeUnion output_type) {
// Eagerly fold representation changes for constants.
switch (node->opcode()) {
}
case IrOpcode::kFloat64Constant:
return node; // No change necessary.
+ case IrOpcode::kFloat32Constant:
+ return jsgraph()->Float64Constant(OpParameter<float>(node));
default:
break;
}
}
} else if (output_type & kRepTagged) {
op = simplified()->ChangeTaggedToFloat64();
+ } else if (output_type & kRepFloat32) {
+ op = machine()->ChangeFloat32ToFloat64();
} else {
return TypeError(node, output_type, kRepFloat64);
}
return jsgraph()->graph()->NewNode(op, node);
}
+ Node* MakeInt32Constant(double value) {
+ if (value < 0) {
+ DCHECK(IsInt32Double(value));
+ int32_t iv = static_cast<int32_t>(value);
+ return jsgraph()->Int32Constant(iv);
+ } else {
+ DCHECK(IsUint32Double(value));
+ int32_t iv = static_cast<int32_t>(static_cast<uint32_t>(value));
+ return jsgraph()->Int32Constant(iv);
+ }
+ }
+
+ Node* GetTruncatedWord32For(Node* node, MachineTypeUnion output_type) {
+ // Eagerly fold truncations for constants.
+ switch (node->opcode()) {
+ case IrOpcode::kInt32Constant:
+ return node; // No change necessary.
+ case IrOpcode::kFloat32Constant:
+ return jsgraph()->Int32Constant(
+ DoubleToInt32(OpParameter<float>(node)));
+ case IrOpcode::kNumberConstant:
+ case IrOpcode::kFloat64Constant:
+ return jsgraph()->Int32Constant(
+ DoubleToInt32(OpParameter<double>(node)));
+ default:
+ break;
+ }
+ // Select the correct X -> Word32 truncation operator.
+ const Operator* op = NULL;
+ if (output_type & kRepFloat64) {
+ op = machine()->TruncateFloat64ToInt32();
+ } else if (output_type & kRepFloat32) {
+ node = InsertChangeFloat32ToFloat64(node);
+ op = machine()->TruncateFloat64ToInt32();
+ } else if (output_type & kRepTagged) {
+ node = InsertChangeTaggedToFloat64(node);
+ op = machine()->TruncateFloat64ToInt32();
+ } else {
+ return TypeError(node, output_type, kRepWord32);
+ }
+ return jsgraph()->graph()->NewNode(op, node);
+ }
+
Node* GetWord32RepresentationFor(Node* node, MachineTypeUnion output_type,
bool use_unsigned) {
// Eagerly fold representation changes for constants.
switch (node->opcode()) {
case IrOpcode::kInt32Constant:
return node; // No change necessary.
+ case IrOpcode::kFloat32Constant:
+ return MakeInt32Constant(OpParameter<float>(node));
case IrOpcode::kNumberConstant:
- case IrOpcode::kFloat64Constant: {
- double value = OpParameter<double>(node);
- if (value < 0) {
- DCHECK(IsInt32Double(value));
- int32_t iv = static_cast<int32_t>(value);
- return jsgraph()->Int32Constant(iv);
- } else {
- DCHECK(IsUint32Double(value));
- int32_t iv = static_cast<int32_t>(static_cast<uint32_t>(value));
- return jsgraph()->Int32Constant(iv);
- }
- }
+ case IrOpcode::kFloat64Constant:
+ return MakeInt32Constant(OpParameter<double>(node));
default:
break;
}
} else {
op = machine()->ChangeFloat64ToInt32();
}
+ } else if (output_type & kRepFloat32) {
+ node = InsertChangeFloat32ToFloat64(node); // float32 -> float64 -> int32
+ if (output_type & kTypeUint32 || use_unsigned) {
+ op = machine()->ChangeFloat64ToUint32();
+ } else {
+ op = machine()->ChangeFloat64ToInt32();
+ }
} else if (output_type & kRepTagged) {
if (output_type & kTypeUint32 || use_unsigned) {
op = simplified()->ChangeTaggedToUint32();
case IrOpcode::kNumberMultiply:
return machine()->Int32Mul();
case IrOpcode::kNumberDivide:
- return machine()->Int32UDiv();
+ return machine()->Uint32Div();
case IrOpcode::kNumberModulus:
- return machine()->Int32UMod();
+ return machine()->Uint32Mod();
case IrOpcode::kNumberEqual:
return machine()->Word32Equal();
case IrOpcode::kNumberLessThan:
MachineTypeUnion use) {
type_error_ = true;
if (!testing_type_errors_) {
- OStringStream out_str;
+ std::ostringstream out_str;
out_str << static_cast<MachineType>(output_type);
- OStringStream use_str;
+ std::ostringstream use_str;
use_str << static_cast<MachineType>(use);
V8_Fatal(__FILE__, __LINE__,
"RepresentationChangerError: node #%d:%s of "
"%s cannot be changed to %s",
- node->id(), node->op()->mnemonic(), out_str.c_str(),
- use_str.c_str());
+ node->id(), node->op()->mnemonic(), out_str.str().c_str(),
+ use_str.str().c_str());
}
return node;
}
+ Node* InsertChangeFloat32ToFloat64(Node* node) {
+ return jsgraph()->graph()->NewNode(machine()->ChangeFloat32ToFloat64(),
+ node);
+ }
+
+ Node* InsertChangeTaggedToFloat64(Node* node) {
+ return jsgraph()->graph()->NewNode(simplified()->ChangeTaggedToFloat64(),
+ node);
+ }
+
JSGraph* jsgraph() { return jsgraph_; }
Isolate* isolate() { return isolate_; }
SimplifiedOperatorBuilder* simplified() { return simplified_; }
MachineOperatorBuilder* machine() { return jsgraph()->machine(); }
};
-}
-}
-} // namespace v8::internal::compiler
+
+} // namespace compiler
+} // namespace internal
+} // namespace v8
#endif // V8_COMPILER_REPRESENTATION_CHANGE_H_