Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavin McCall2022-05-16 13:35:29 +0000
committerJonah Graham2022-05-25 15:43:22 +0000
commit1ec4ae52c1de8352acf8bf9f0aab8936eeb554ec (patch)
tree1ec6ab35bd8887f2826b70b9fcc03aa1b3be16ef
parent9b05a213eb55676d6e18292c4de6012508ede15e (diff)
downloadorg.eclipse.cdt-1ec4ae52c1de8352acf8bf9f0aab8936eeb554ec.tar.gz
org.eclipse.cdt-1ec4ae52c1de8352acf8bf9f0aab8936eeb554ec.tar.xz
org.eclipse.cdt-1ec4ae52c1de8352acf8bf9f0aab8936eeb554ec.zip
Bug 579934 support constexpr evaluation of __builtin_ffs[l,ll]
-rw-r--r--core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/cxx14/constexpr/IntegralValueTests.java5
-rw-r--r--core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/cxx14/constexpr/TestBase.java4
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/GCCBuiltinSymbolProvider.java41
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ITypeMarshalBuffer.java2
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPBuiltinParameter.java10
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/ExecBuiltin.java89
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPLinkage.java3
7 files changed, 145 insertions, 9 deletions
diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/cxx14/constexpr/IntegralValueTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/cxx14/constexpr/IntegralValueTests.java
index 43bf85a6144..48160677923 100644
--- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/cxx14/constexpr/IntegralValueTests.java
+++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/cxx14/constexpr/IntegralValueTests.java
@@ -269,4 +269,9 @@ public abstract class IntegralValueTests extends TestBase {
public void testHexLiteral() throws Exception {
assertEvaluationEquals(42);
}
+
+ // constexpr int x = __builtin_ffs(0) + __builtin_ffs(16);
+ public void testBuiltinFfs() throws Exception {
+ assertEvaluationEquals(5);
+ }
} \ No newline at end of file
diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/cxx14/constexpr/TestBase.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/cxx14/constexpr/TestBase.java
index 1070ee2f554..79badd6a337 100644
--- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/cxx14/constexpr/TestBase.java
+++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/cxx14/constexpr/TestBase.java
@@ -21,7 +21,7 @@ import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
import org.eclipse.cdt.core.dom.ast.IValue;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTInitializerClause;
import org.eclipse.cdt.core.dom.parser.IScannerExtensionConfiguration;
-import org.eclipse.cdt.core.dom.parser.cpp.ANSICPPParserExtensionConfiguration;
+import org.eclipse.cdt.core.dom.parser.cpp.GPPParserExtensionConfiguration;
import org.eclipse.cdt.core.dom.parser.cpp.GPPScannerExtensionConfiguration;
import org.eclipse.cdt.core.dom.parser.cpp.ICPPParserExtensionConfiguration;
import org.eclipse.cdt.core.index.IIndex;
@@ -194,7 +194,7 @@ public abstract class TestBase extends IndexBindingResolutionTestBase {
IScanner scanner = createScanner(FileContent.create(TEST_CODE, code.toCharArray()), ParserLanguage.CPP,
ParserMode.COMPLETE_PARSE, SCANNER_INFO);
AbstractGNUSourceCodeParser parser = null;
- ICPPParserExtensionConfiguration config = new ANSICPPParserExtensionConfiguration();
+ ICPPParserExtensionConfiguration config = new GPPParserExtensionConfiguration();
parser = new GNUCPPSourceParser(scanner, ParserMode.COMPLETE_PARSE, NULL_LOG, config, null);
parser.setMaximumTrivialExpressionsInAggregateInitializers(Integer.MAX_VALUE);
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/GCCBuiltinSymbolProvider.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/GCCBuiltinSymbolProvider.java
index b453dfe5e10..b5ab4d3b5df 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/GCCBuiltinSymbolProvider.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/GCCBuiltinSymbolProvider.java
@@ -53,6 +53,8 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPImplicitTypedef;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPPointerType;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPQualifierType;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPReferenceType;
+import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPExecution;
+import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExecBuiltin;
/**
* This is the IBuiltinBindingsProvider used to implement the "Other" built-in GCC symbols defined:
@@ -188,6 +190,8 @@ public class GCCBuiltinSymbolProvider implements IBuiltinBindingsProvider {
function("bool", "__atomic_always_lock_free", "size_t", "void*");
function("bool", "__atomic_is_lock_free", "size_t", "void*");
+ ICPPExecution builtinFfs = new ExecBuiltin(ExecBuiltin.BUILTIN_FFS);
+
// Other Builtins (https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html) [incomplete]
function("void", "__builtin_abort");
function("int", "__builtin_abs", "int");
@@ -277,9 +281,9 @@ public class GCCBuiltinSymbolProvider implements IBuiltinBindingsProvider {
function("double", "__builtin_fdim", "double", "double");
function("float", "__builtin_fdimf", "float", "float");
function("long double", "__builtin_fdiml", "long double", "long double");
- function("int", "__builtin_ffs", "unsigned int");
- function("int", "__builtin_ffsl", "unsigned long");
- function("int", "__builtin_ffsll", "unsigned long long");
+ function("int", "__builtin_ffs", builtinFfs, "unsigned int");
+ function("int", "__builtin_ffsl", builtinFfs, "unsigned long");
+ function("int", "__builtin_ffsll", builtinFfs, "unsigned long long");
function("double", "__builtin_floor", "double");
function("float", "__builtin_floorf", "float");
function("long double", "__builtin_floorl", "long double");
@@ -501,6 +505,13 @@ public class GCCBuiltinSymbolProvider implements IBuiltinBindingsProvider {
}
private void function(String returnType, String name, String... parameterTypes) {
+ function(returnType, name, null, parameterTypes);
+ }
+
+ /*
+ * Create a function which can possibly be constexpr-evaluated
+ */
+ private void function(String returnType, String name, ICPPExecution exec, String... parameterTypes) {
int len = parameterTypes.length;
boolean varargs = len > 0 && parameterTypes[len - 1].equals("...");
if (varargs)
@@ -511,14 +522,14 @@ public class GCCBuiltinSymbolProvider implements IBuiltinBindingsProvider {
for (int i = 0; i < len; i++) {
IType pType = toType(parameterTypes[i]);
pTypes[i] = pType;
- theParms[i] = fCpp ? new CPPBuiltinParameter(pType) : new CBuiltinParameter(pType);
+ theParms[i] = fCpp ? new CPPBuiltinParameter(pType, i) : new CBuiltinParameter(pType);
}
IType rt = toType(returnType);
IFunctionType ft = fCpp ? new CPPFunctionType(rt, pTypes, null) : new CFunctionType(rt, pTypes);
IBinding b = fCpp
- ? new CPPImplicitFunction(toCharArray(name), fScope, (ICPPFunctionType) ft, (ICPPParameter[]) theParms,
- false, varargs)
+ ? new CPPBuiltinImplicitFunction(toCharArray(name), fScope, (ICPPFunctionType) ft,
+ (ICPPParameter[]) theParms, varargs, exec)
: new CImplicitFunction(toCharArray(name), fScope, ft, theParms, varargs);
fBindingList.add(b);
}
@@ -661,4 +672,22 @@ public class GCCBuiltinSymbolProvider implements IBuiltinBindingsProvider {
public boolean isKnownBuiltin(char[] builtinName) {
return fKnownBuiltins.containsKey(builtinName);
}
+
+ /*
+ * A builtin function which can be evaluated in a constexpr context
+ */
+ private static class CPPBuiltinImplicitFunction extends CPPImplicitFunction {
+ private ICPPExecution execution;
+
+ public CPPBuiltinImplicitFunction(char[] name, IScope scope, ICPPFunctionType type, ICPPParameter[] params,
+ boolean takesVarArgs, ICPPExecution execution) {
+ super(name, scope, type, params, true, takesVarArgs);
+ this.execution = execution;
+ }
+
+ @Override
+ public ICPPExecution getFunctionBodyExecution() {
+ return execution;
+ }
+ }
}
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ITypeMarshalBuffer.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ITypeMarshalBuffer.java
index cc215747ed2..b7e352d7bf1 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ITypeMarshalBuffer.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ITypeMarshalBuffer.java
@@ -52,7 +52,7 @@ public interface ITypeMarshalBuffer {
EXEC_DECLARATION_STATEMENT = 0x05, EXEC_DECLARATOR = 0x06, EXEC_DEFAULT = 0x07,
EXEC_SIMPLE_DECLARATION = 0x08, EXEC_RETURN = 0x09, EXEC_EXPRESSION_STATEMENT = 0x0A, EXEC_IF = 0x0B,
EXEC_WHILE = 0x0C, EXEC_DO = 0x0D, EXEC_FOR = 0x0E, EXEC_RANGE_BASED_FOR = 0x0F, EXEC_SWITCH = 0x10,
- EXEC_CONSTRUCTOR_CHAIN = 0x11, EXEC_INCOMPLETE = 0x12;
+ EXEC_CONSTRUCTOR_CHAIN = 0x11, EXEC_INCOMPLETE = 0x12, EXEC_BUILTIN = 0x13;
// Can add more executions up to 0x1C, after that it will collide with TypeMarshalBuffer.UNSTORABLE_TYPE.
static final short KIND_MASK = 0x001F;
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPBuiltinParameter.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPBuiltinParameter.java
index 3dd21dc3de9..754da65a108 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPBuiltinParameter.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPBuiltinParameter.java
@@ -38,9 +38,16 @@ public class CPPBuiltinParameter extends PlatformObject implements ICPPParameter
}
private IType type;
+ private int position;
public CPPBuiltinParameter(IType type) {
this.type = type;
+ this.position = -1;
+ }
+
+ public CPPBuiltinParameter(IType type, int position) {
+ this.type = type;
+ this.position = position;
}
@Override
@@ -75,6 +82,9 @@ public class CPPBuiltinParameter extends PlatformObject implements ICPPParameter
@Override
public String getName() {
+ if (position != -1) {
+ return "arg" + position; //$NON-NLS-1$
+ }
return ""; //$NON-NLS-1$
}
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/ExecBuiltin.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/ExecBuiltin.java
new file mode 100644
index 00000000000..338ef00240f
--- /dev/null
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/ExecBuiltin.java
@@ -0,0 +1,89 @@
+/*******************************************************************************
+* Copyright (c) 2022 Davin McCall and others.
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Davin McCall - initial API and implementation
+*******************************************************************************/
+package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics;
+
+import org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory;
+import org.eclipse.cdt.core.dom.ast.IBasicType.Kind;
+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.cpp.CPPBasicType;
+import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPBuiltinParameter;
+import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation;
+import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation.ConstexprEvaluationContext;
+import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPExecution;
+import org.eclipse.cdt.internal.core.dom.parser.cpp.InstantiationContext;
+import org.eclipse.core.runtime.CoreException;
+
+/**
+ * Constexpr-evaluation for compiler builtin functions.
+ */
+public class ExecBuiltin implements ICPPExecution {
+ public final static short BUILTIN_FFS = 0;
+
+ private static IType intType = new CPPBasicType(Kind.eInt, 0);
+
+ private short funcId;
+
+ public ExecBuiltin(short funcId) {
+ this.funcId = funcId;
+ }
+
+ @Override
+ public ICPPExecution instantiate(InstantiationContext context, int maxDepth) {
+ return this;
+ }
+
+ @Override
+ public ICPPExecution executeForFunctionCall(ActivationRecord record, ConstexprEvaluationContext context) {
+
+ switch (funcId) {
+ case BUILTIN_FFS:
+ return executeBuiltinFfs(record, context);
+ }
+ return null;
+ }
+
+ private ICPPExecution executeBuiltinFfs(ActivationRecord record, ConstexprEvaluationContext context) {
+ ICPPEvaluation arg0 = record.getVariable(new CPPBuiltinParameter(null, 0));
+
+ IValue argValue = arg0.getValue();
+ if (!(argValue instanceof IntegralValue))
+ return null;
+
+ // __builtin_ffs returns 0 if arg is 0, or 1+count where count is the number of trailing 0 bits
+ long arg = argValue.numberValue().longValue();
+ if (arg == 0) {
+ return new ExecReturn(new EvalFixed(intType, ValueCategory.PRVALUE, IntegralValue.create(0)));
+ }
+ int count = 0;
+ while ((arg & 1) == 0) {
+ arg >>= 1;
+ count++;
+ }
+ return new ExecReturn(new EvalFixed(intType, ValueCategory.PRVALUE, IntegralValue.create(count + 1)));
+ }
+
+ @Override
+ public void marshal(ITypeMarshalBuffer buffer, boolean includeValue) throws CoreException {
+ buffer.putShort(ITypeMarshalBuffer.EXEC_BUILTIN);
+ buffer.putShort(funcId);
+ }
+
+ public static ICPPExecution unmarshal(short firstBytes, ITypeMarshalBuffer buffer) throws CoreException {
+ short funcId = buffer.getShort();
+ return new ExecBuiltin(funcId);
+ }
+}
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPLinkage.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPLinkage.java
index 9b683b08a2e..991f3ef73eb 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPLinkage.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPLinkage.java
@@ -143,6 +143,7 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalTypeId;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalUnary;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalUnaryTypeID;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExecBreak;
+import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExecBuiltin;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExecCase;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExecCompoundStatement;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExecConstructorChain;
@@ -1771,6 +1772,8 @@ class PDOMCPPLinkage extends PDOMLinkage implements IIndexCPPBindingConstants {
return ExecConstructorChain.unmarshal(firstBytes, buffer);
case ITypeMarshalBuffer.EXEC_INCOMPLETE:
return ExecIncomplete.unmarshal(firstBytes, buffer);
+ case ITypeMarshalBuffer.EXEC_BUILTIN:
+ return ExecBuiltin.unmarshal(firstBytes, buffer);
}
throw new CoreException(CCorePlugin.createStatus("Cannot unmarshal an execution, first bytes=" + firstBytes)); //$NON-NLS-1$
}

Back to the top