mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-21 21:52:10 +02:00
Bug 580325 - constexpr evaluation of builtins for clrsb, clz (#52)
Adds constexpr evaluation for some additional compiler builtins. This is probably the last lot few builtins that can reasonably be constexpr-evaluated in CDT.
This commit is contained in:
parent
ef195dbb73
commit
6445ec4890
3 changed files with 116 additions and 8 deletions
|
@ -340,4 +340,24 @@ public abstract class IntegralValueTests extends TestBase {
|
|||
public void testBuiltinAbsNarrowing() throws Exception {
|
||||
assertEvaluationEquals(1);
|
||||
}
|
||||
|
||||
// constexpr int x = __builtin_clrsb(0xFFFFFFFF);
|
||||
public void testBuiltinClrsb() throws Exception {
|
||||
assertEvaluationEquals(31);
|
||||
}
|
||||
|
||||
// constexpr int x = __builtin_clrsb(555);
|
||||
public void testBuiltinClrsbPositive() throws Exception {
|
||||
assertEvaluationEquals(21);
|
||||
}
|
||||
|
||||
// constexpr int x = __builtin_clz(0x8000);
|
||||
public void testBuiltinClz() throws Exception {
|
||||
assertEvaluationEquals(16);
|
||||
}
|
||||
|
||||
// constexpr int x = __builtin_clz(-17);
|
||||
public void testBuiltinClzNegative() throws Exception {
|
||||
assertEvaluationEquals(0);
|
||||
}
|
||||
}
|
|
@ -205,6 +205,12 @@ public class GCCBuiltinSymbolProvider implements IBuiltinBindingsProvider {
|
|||
ICPPExecution builtinAbs = new ExecBuiltin(ExecBuiltin.BUILTIN_ABS);
|
||||
ICPPExecution builtinLabs = new ExecBuiltin(ExecBuiltin.BUILTIN_LABS);
|
||||
ICPPExecution builtinLlabs = new ExecBuiltin(ExecBuiltin.BUILTIN_LLABS);
|
||||
ICPPExecution builtinClrsb = new ExecBuiltin(ExecBuiltin.BUILTIN_CLRSB);
|
||||
ICPPExecution builtinClrsbl = new ExecBuiltin(ExecBuiltin.BUILTIN_CLRSBL);
|
||||
ICPPExecution builtinClrsbll = new ExecBuiltin(ExecBuiltin.BUILTIN_CLRSBLL);
|
||||
ICPPExecution builtinClz = new ExecBuiltin(ExecBuiltin.BUILTIN_CLZ);
|
||||
ICPPExecution builtinClzl = new ExecBuiltin(ExecBuiltin.BUILTIN_CLZL);
|
||||
ICPPExecution builtinClzll = new ExecBuiltin(ExecBuiltin.BUILTIN_CLZLL);
|
||||
|
||||
// Other Builtins (https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html) [incomplete]
|
||||
function("void", "__builtin_abort");
|
||||
|
@ -243,12 +249,12 @@ public class GCCBuiltinSymbolProvider implements IBuiltinBindingsProvider {
|
|||
function("float", "__builtin_cimagf", "complex float");
|
||||
function("long double", "__builtin_cimagl", "complex long double");
|
||||
function("void", "__builtin___clear_cache", "void*", "void*");
|
||||
function("int", "__builtin_clrsb", "int");
|
||||
function("int", "__builtin_clrsbl", "long");
|
||||
function("int", "__builtin_clrsbll", "long long");
|
||||
function("int", "__builtin_clz", "unsigned int");
|
||||
function("int", "__builtin_clzl", "unsigned long");
|
||||
function("int", "__builtin_clzll", "unsigned long long");
|
||||
function("int", "__builtin_clrsb", builtinClrsb, "int");
|
||||
function("int", "__builtin_clrsbl", builtinClrsbl, "long");
|
||||
function("int", "__builtin_clrsbll", builtinClrsbll, "long long");
|
||||
function("int", "__builtin_clz", builtinClz, "unsigned int");
|
||||
function("int", "__builtin_clzl", builtinClzl, "unsigned long");
|
||||
function("int", "__builtin_clzll", builtinClzll, "unsigned long long");
|
||||
function("complex double", "__builtin_conj", "complex double");
|
||||
function("complex float", "__builtin_conjf", "complex float");
|
||||
function("complex long double", "__builtin_conjl", "complex long double");
|
||||
|
@ -330,7 +336,7 @@ public class GCCBuiltinSymbolProvider implements IBuiltinBindingsProvider {
|
|||
function("int", "__builtin_ilogb", "double");
|
||||
function("int", "__builtin_ilogbf", "float");
|
||||
function("int", "__builtin_ilogbl", "long double");
|
||||
function("long long", "__builtin_imaxabs", "long long");
|
||||
function("long long", "__builtin_imaxabs", builtinLlabs, "long long");
|
||||
function("double", "__builtin_inf");
|
||||
function("_Decimal32", "__builtin_infd32");
|
||||
function("_Decimal64", "__builtin_infd64");
|
||||
|
|
|
@ -19,6 +19,8 @@ import org.eclipse.cdt.core.dom.ast.IType;
|
|||
import org.eclipse.cdt.core.dom.ast.IValue;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.ITypeMarshalBuffer;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.IntegralValue;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.SizeofCalculator;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.SizeofCalculator.SizeAndAlignment;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPBasicType;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPBuiltinParameter;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation;
|
||||
|
@ -33,7 +35,9 @@ import org.eclipse.core.runtime.CoreException;
|
|||
public class ExecBuiltin implements ICPPExecution {
|
||||
public final static short BUILTIN_FFS = 0, BUILTIN_FFSL = 1, BUILTIN_FFSLL = 2, BUILTIN_CTZ = 3, BUILTIN_CTZL = 4,
|
||||
BUILTIN_CTZLL = 5, BUILTIN_POPCOUNT = 6, BUILTIN_POPCOUNTL = 7, BUILTIN_POPCOUNTLL = 8, BUILTIN_PARITY = 9,
|
||||
BUILTIN_PARITYL = 10, BUILTIN_PARITYLL = 11, BUILTIN_ABS = 12, BUILTIN_LABS = 13, BUILTIN_LLABS = 14;
|
||||
BUILTIN_PARITYL = 10, BUILTIN_PARITYLL = 11, BUILTIN_ABS = 12, BUILTIN_LABS = 13, BUILTIN_LLABS = 14,
|
||||
BUILTIN_CLRSB = 15, BUILTIN_CLRSBL = 16, BUILTIN_CLRSBLL = 17, BUILTIN_CLZ = 18, BUILTIN_CLZL = 19,
|
||||
BUILTIN_CLZLL = 20;
|
||||
|
||||
private static IType intType = new CPPBasicType(Kind.eInt, 0);
|
||||
private static IType longType = new CPPBasicType(Kind.eInt, CPPBasicType.IS_LONG);
|
||||
|
@ -84,6 +88,18 @@ public class ExecBuiltin implements ICPPExecution {
|
|||
return executeBuiltinAbs(record, context, longType);
|
||||
case BUILTIN_LLABS:
|
||||
return executeBuiltinAbs(record, context, longlongType);
|
||||
case BUILTIN_CLRSB:
|
||||
return executeBuiltinClrsb(record, context, intType);
|
||||
case BUILTIN_CLRSBL:
|
||||
return executeBuiltinClrsb(record, context, longType);
|
||||
case BUILTIN_CLRSBLL:
|
||||
return executeBuiltinClrsb(record, context, longlongType);
|
||||
case BUILTIN_CLZ:
|
||||
return executeBuiltinClz(record, context, intType);
|
||||
case BUILTIN_CLZL:
|
||||
return executeBuiltinClz(record, context, longType);
|
||||
case BUILTIN_CLZLL:
|
||||
return executeBuiltinClz(record, context, longlongType);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -166,6 +182,9 @@ public class ExecBuiltin implements ICPPExecution {
|
|||
return executeBuiltinPopcountParity(record, context, true, argType);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return an execution implementing __builtin_abs
|
||||
*/
|
||||
private ICPPExecution executeBuiltinAbs(ActivationRecord record, ConstexprEvaluationContext context,
|
||||
IType argType) {
|
||||
ICPPEvaluation arg0 = record.getVariable(new CPPBuiltinParameter(null, 0));
|
||||
|
@ -182,6 +201,69 @@ public class ExecBuiltin implements ICPPExecution {
|
|||
return new ExecReturn(new EvalFixed(argType, ValueCategory.PRVALUE, IntegralValue.create(result)));
|
||||
}
|
||||
|
||||
/*
|
||||
* Return an execution implementing __builtin_clsrb (count leading "redundant" sign bits)
|
||||
*/
|
||||
private ICPPExecution executeBuiltinClrsb(ActivationRecord record, ConstexprEvaluationContext context,
|
||||
IType argType) {
|
||||
ICPPEvaluation arg0 = record.getVariable(new CPPBuiltinParameter(null, 0));
|
||||
|
||||
SizeAndAlignment sizeToType = SizeofCalculator.getSizeAndAlignment(argType);
|
||||
if (sizeToType.size > 8)
|
||||
return null; // can't handle too-large type
|
||||
|
||||
IValue argValue = arg0.getValue();
|
||||
Number argNumber = argValue.numberValue();
|
||||
if (argNumber == null)
|
||||
return null;
|
||||
|
||||
long argLong = argNumber.longValue();
|
||||
long signBit = 1L << (sizeToType.size * 8 - 1);
|
||||
int result = 0;
|
||||
long valueBit = signBit >>> 1;
|
||||
|
||||
if ((argLong & signBit) == 0) {
|
||||
// if positive, invert all bits so we can unconditionally count 1 bits
|
||||
argLong = ~argLong;
|
||||
}
|
||||
|
||||
while ((argLong & valueBit) != 0) {
|
||||
result++;
|
||||
valueBit >>>= 1;
|
||||
}
|
||||
|
||||
return new ExecReturn(new EvalFixed(intType, ValueCategory.PRVALUE, IntegralValue.create(result)));
|
||||
}
|
||||
|
||||
private ICPPExecution executeBuiltinClz(ActivationRecord record, ConstexprEvaluationContext context,
|
||||
IType argType) {
|
||||
ICPPEvaluation arg0 = record.getVariable(new CPPBuiltinParameter(null, 0));
|
||||
|
||||
SizeAndAlignment sizeToType = SizeofCalculator.getSizeAndAlignment(argType);
|
||||
if (sizeToType.size > 8)
|
||||
return null; // can't handle too-large type
|
||||
|
||||
IValue argValue = arg0.getValue();
|
||||
Number argNumber = argValue.numberValue();
|
||||
if (argNumber == null)
|
||||
return null;
|
||||
|
||||
long argLong = argNumber.longValue();
|
||||
long valueBit = 1L << (sizeToType.size * 8 - 1);
|
||||
int result = 0;
|
||||
|
||||
// Note that __builtin_clz(0) is supposedly undefined, but GCC (12.1) apparently returns
|
||||
// the bit size of int, so we'll make sure to do the same.
|
||||
while ((argLong & valueBit) == 0) {
|
||||
result++;
|
||||
valueBit >>>= 1;
|
||||
if (valueBit == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
return new ExecReturn(new EvalFixed(intType, ValueCategory.PRVALUE, IntegralValue.create(result)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void marshal(ITypeMarshalBuffer buffer, boolean includeValue) throws CoreException {
|
||||
buffer.putShort(ITypeMarshalBuffer.EXEC_BUILTIN);
|
||||
|
|
Loading…
Add table
Reference in a new issue