Merge pull request #3151 from dbartol/dbartol/floats

C++: Better support for complex numbers in IR and AST
This commit is contained in:
Jonas Jensen
2020-04-20 16:27:20 +02:00
committed by GitHub
16 changed files with 2691 additions and 61 deletions

View File

@@ -12,7 +12,9 @@ private newtype TIRType =
TIRBooleanType(int byteSize) { Language::hasBooleanType(byteSize) } or
TIRSignedIntegerType(int byteSize) { Language::hasSignedIntegerType(byteSize) } or
TIRUnsignedIntegerType(int byteSize) { Language::hasUnsignedIntegerType(byteSize) } or
TIRFloatingPointType(int byteSize) { Language::hasFloatingPointType(byteSize) } or
TIRFloatingPointType(int byteSize, int base, Language::TypeDomain domain) {
Language::hasFloatingPointType(byteSize, base, domain)
} or
TIRAddressType(int byteSize) { Language::hasAddressType(byteSize) } or
TIRFunctionAddressType(int byteSize) { Language::hasFunctionAddressType(byteSize) } or
TIROpaqueType(Language::OpaqueTypeTag tag, int byteSize) {
@@ -104,7 +106,7 @@ private class IRSizedType extends IRType {
this = TIRBooleanType(byteSize) or
this = TIRSignedIntegerType(byteSize) or
this = TIRUnsignedIntegerType(byteSize) or
this = TIRFloatingPointType(byteSize) or
this = TIRFloatingPointType(byteSize, _, _) or
this = TIRAddressType(byteSize) or
this = TIRFunctionAddressType(byteSize) or
this = TIROpaqueType(_, byteSize)
@@ -133,7 +135,7 @@ class IRNumericType extends IRSizedType {
IRNumericType() {
this = TIRSignedIntegerType(byteSize) or
this = TIRUnsignedIntegerType(byteSize) or
this = TIRFloatingPointType(byteSize)
this = TIRFloatingPointType(byteSize, _, _)
}
}
@@ -171,14 +173,43 @@ class IRUnsignedIntegerType extends IRNumericType, TIRUnsignedIntegerType {
* A floating-point type.
*/
class IRFloatingPointType extends IRNumericType, TIRFloatingPointType {
final override string toString() { result = "float" + byteSize.toString() }
final private int base;
final private Language::TypeDomain domain;
IRFloatingPointType() { this = TIRFloatingPointType(_, base, domain) }
final override string toString() {
result = getDomainPrefix() + getBaseString() + byteSize.toString()
}
final override Language::LanguageType getCanonicalLanguageType() {
result = Language::getCanonicalFloatingPointType(byteSize)
result = Language::getCanonicalFloatingPointType(byteSize, base, domain)
}
pragma[noinline]
final override int getByteSize() { result = byteSize }
/** Gets the numeric base of the type. Can be either 2 (binary) or 10 (decimal). */
final int getBase() { result = base }
/**
* Gets the type domain of the type. Can be `RealDomain`, `ComplexDomain`, or `ImaginaryDomain`.
*/
final Language::TypeDomain getDomain() { result = domain }
private string getBaseString() {
base = 2 and result = "float"
or
base = 10 and result = "decimal"
}
private string getDomainPrefix() {
domain instanceof Language::RealDomain and result = ""
or
domain instanceof Language::ComplexDomain and result = "c"
or
domain instanceof Language::ImaginaryDomain and result = "i"
}
}
/**

View File

@@ -61,9 +61,13 @@ predicate hasUnsignedIntegerType(int byteSize) {
}
/**
* Holds if an `IRFloatingPointType` with the specified `byteSize` should exist.
* Holds if an `IRFloatingPointType` with the specified size, base, and type domain should exist.
*/
predicate hasFloatingPointType(int byteSize) { byteSize = any(FloatingPointType type).getSize() }
predicate hasFloatingPointType(int byteSize, int base, Language::TypeDomain domain) {
byteSize = any(FloatingPointType type).getSize() and
base = 2 and
domain instanceof Language::RealDomain
}
private predicate isPointerIshType(Type type) {
type instanceof PointerType or
@@ -314,9 +318,11 @@ CSharpPRValueType getCanonicalUnsignedIntegerType(int byteSize) {
/**
* Gets the `CSharpType` that is the canonical type for an `IRFloatingPointType` with the specified
* `byteSize`.
* size, base, and type domain.
*/
CSharpPRValueType getCanonicalFloatingPointType(int byteSize) {
CSharpPRValueType getCanonicalFloatingPointType(int byteSize, int base, Language::TypeDomain domain) {
base = 2 and
domain instanceof Language::RealDomain and
result = TPRValueType(any(FloatingPointType type | type.getSize() = byteSize))
}

View File

@@ -28,6 +28,44 @@ class IntegralType = CSharp::IntegralType;
class FloatingPointType = CSharp::FloatingPointType;
private newtype TTypeDomain = TRealDomain()
/**
* The type domain of a floating-point type. One of `RealDomain`, `ComplexDomain`, or
* `ImaginaryDomain`.
*/
class TypeDomain extends TTypeDomain {
/** Gets a textual representation of this type domain. */
string toString() { none() }
}
/**
* The type domain of a floating-point type that represents a real number.
*/
class RealDomain extends TypeDomain, TRealDomain {
final override string toString() { result = "real" }
}
/**
* The type domain of a floating-point type that represents a complex number. Not currently used in
* C#.
*/
class ComplexDomain extends TypeDomain {
ComplexDomain() { none() }
final override string toString() { result = "complex" }
}
/**
* The type domain of a floating-point type that represents an imaginary number. Not currently used
* in C#.
*/
class ImaginaryDomain extends TypeDomain {
ImaginaryDomain() { none() }
final override string toString() { result = "imaginary" }
}
private newtype TClassDerivation =
// Note that this is the `Class` type exported from this module, not CSharp::Class.
MkClassDerivation(Class base, Class derived) { derived.getABaseType() = base }