已合并
feat(jit): support pointer and struct tiling constants #5719
XuebinYang创建于 12 天前
feat(jit): support pointer and struct tiling constants #5719
已合并
共 26 个文件变更+1146-605
| @@ -458,6 +458,9 @@ class TestStaticCompileResourceGenerator(unittest.TestCase): | |||
| 458 | self.assertEqual(manifest["resource_id"], self.resource_id) | 458 | self.assertEqual(manifest["resource_id"], self.resource_id) |
| 459 | self.assertEqual(manifest["kernels"][0]["kernel_name"], "add_custom_100000") | 459 | self.assertEqual(manifest["kernels"][0]["kernel_name"], "add_custom_100000") |
| 460 | self.assertEqual(manifest["kernels"][0]["constant_infos"][0]["byte_size"], 24) | 460 | self.assertEqual(manifest["kernels"][0]["constant_infos"][0]["byte_size"], 24) |
| 461 | + self.assertEqual( | ||
| 462 | + manifest["kernels"][0]["constant_infos"][0]["arg_type"], "pointer" | ||
| 463 | + ) | ||
| 461 | self.assertTrue(os.path.isdir(os.path.join(self.output_dir, "resources"))) | 464 | self.assertTrue(os.path.isdir(os.path.join(self.output_dir, "resources"))) |
| 462 | 465 | ||
| 463 | def test_basic_mix_manifest_uses_static_wrapper_and_tiling_template(self): | 466 | def test_basic_mix_manifest_uses_static_wrapper_and_tiling_template(self): |
| @@ -673,6 +676,7 @@ class TestStaticCompileResourceGenerator(unittest.TestCase): | |||
| 673 | { | 676 | { |
| 674 | "name": "tiling_data", | 677 | "name": "tiling_data", |
| 675 | "parameter_index": 4, | 678 | "parameter_index": 4, |
| 679 | + "arg_type": "pointer", | ||
| 676 | "byte_size": 8, | 680 | "byte_size": 8, |
| 677 | "file": "${resource}/resources/include/add_custom_tiling_data.h", | 681 | "file": "${resource}/resources/include/add_custom_tiling_data.h", |
| 678 | "template": "@@STATIC_VALUE_tiling_data@@", | 682 | "template": "@@STATIC_VALUE_tiling_data@@", |
| @@ -680,6 +684,7 @@ class TestStaticCompileResourceGenerator(unittest.TestCase): | |||
| 680 | { | 684 | { |
| 681 | "name": "block_dim", | 685 | "name": "block_dim", |
| 682 | "parameter_index": 5, | 686 | "parameter_index": 5, |
| 687 | + "arg_type": "pointer", | ||
| 683 | "byte_size": 4, | 688 | "byte_size": 4, |
| 684 | "file": "${resource}/resources/include/add_custom_tiling_data.h", | 689 | "file": "${resource}/resources/include/add_custom_tiling_data.h", |
| 685 | "template": block_dim_template, | 690 | "template": block_dim_template, |
| @@ -21,6 +21,7 @@ file(GLOB ACLRTC_SRC_FILES | |||
| 21 | 21 | ||
| 22 | set(ACLRTC_COMMON_DEPENDENCY_SRC_FILES | 22 | set(ACLRTC_COMMON_DEPENDENCY_SRC_FILES |
| 23 | ${ASCENDC_DIR}/tools/build/common/file_utils.cpp | 23 | ${ASCENDC_DIR}/tools/build/common/file_utils.cpp |
| 24 | + ${ASCENDC_DIR}/tools/build/common/manifest_constant.cpp | ||
| 24 | ${ASCENDC_DIR}/tools/build/common/process_executor.cpp | 25 | ${ASCENDC_DIR}/tools/build/common/process_executor.cpp |
| 25 | ${ASCENDC_DIR}/tools/build/common/directory_cleanup_guard.cpp | 26 | ${ASCENDC_DIR}/tools/build/common/directory_cleanup_guard.cpp |
| 26 | ) | 27 | ) |
| @@ -34,7 +34,6 @@ using ascendc::aclrtc::CompilationCommandExecutionLimits; | |||
| 34 | using ascendc::aclrtc::CompilationCommandKind; | 34 | using ascendc::aclrtc::CompilationCommandKind; |
| 35 | using ascendc::aclrtc::CompilationPlanExecutor; | 35 | using ascendc::aclrtc::CompilationPlanExecutor; |
| 36 | using ascendc::aclrtc::KernelCompilationPlan; | 36 | using ascendc::aclrtc::KernelCompilationPlan; |
| 37 | -using ascendc::aclrtc::KernelCompilationVariant; | ||
| 38 | using ascendc::aclrtc::KernelSpecializationDiagnostics; | 37 | using ascendc::aclrtc::KernelSpecializationDiagnostics; |
| 39 | using namespace mockcpp; | 38 | using namespace mockcpp; |
| 40 | 39 | ||
| @@ -68,9 +67,6 @@ pid_t ReapCommandProcess(pid_t processId, int* waitStatus, int) | |||
| 68 | return waitResult; | 67 | return waitResult; |
| 69 | } | 68 | } |
| 70 | 69 | ||
| 71 | -static_assert( | ||
| 72 | - std::is_same<std::underlying_type_t<KernelCompilationVariant>, uint32_t>::value, | ||
| 73 | - "KernelCompilationVariant must have a stable width"); | ||
| 74 | static_assert( | 70 | static_assert( |
| 75 | std::is_same<std::underlying_type_t<CompilationCommandKind>, uint32_t>::value, | 71 | std::is_same<std::underlying_type_t<CompilationCommandKind>, uint32_t>::value, |
| 76 | "CompilationCommandKind must have a stable width"); | 72 | "CompilationCommandKind must have a stable width"); |
| @@ -9,6 +9,7 @@ | |||
| 9 | */ | 9 | */ |
| 10 | 10 | ||
| 11 | 11 | ||
| 12 | + | ||
| 12 | 13 | ||
| 13 | 14 | ||
| 14 | 15 | ||
| @@ -20,6 +21,7 @@ | |||
| 20 | 21 | ||
| 21 | 22 | ||
| 22 | 23 | ||
| 24 | + | ||
| 23 | 25 | ||
| 24 | 26 | ||
| 25 | namespace { | 27 | namespace { |
| @@ -28,7 +30,6 @@ using Json = nlohmann::json; | |||
| 28 | using ascendc::aclrtc::CompilationCommandKind; | 30 | using ascendc::aclrtc::CompilationCommandKind; |
| 29 | using ascendc::aclrtc::KernelCompilationPlan; | 31 | using ascendc::aclrtc::KernelCompilationPlan; |
| 30 | using ascendc::aclrtc::KernelCompilationPlanBuilder; | 32 | using ascendc::aclrtc::KernelCompilationPlanBuilder; |
| 31 | -using ascendc::aclrtc::KernelCompilationVariant; | ||
| 32 | using ascendc::aclrtc::NormalizedKernelSpecializationRequest; | 33 | using ascendc::aclrtc::NormalizedKernelSpecializationRequest; |
| 33 | 34 | ||
| 34 | class ScopedEnvironmentVariable final { | 35 | class ScopedEnvironmentVariable final { |
| @@ -122,7 +123,9 @@ Json CreateManifest() | |||
| 122 | {{{"kernel_name", "other_kernel"}, {"unsupported_future_field", Json::object()}}, | 123 | {{{"kernel_name", "other_kernel"}, {"unsupported_future_field", Json::object()}}, |
| 123 | {{"kernel_name", "add_custom_100000"}, | 124 | {{"kernel_name", "add_custom_100000"}, |
| 124 | {"constant_infos", Json::array( | 125 | {"constant_infos", Json::array( |
| 125 | - {{{"parameter_index", 0}, | 126 | + {{{"name", "tiling"}, |
| 127 | + {"parameter_index", 0}, | ||
| 128 | + {"arg_type", "pointer"}, | ||
| 126 | {"byte_size", 2}, | 129 | {"byte_size", 2}, |
| 127 | {"file", "${resource}/resources/include/constants.h"}, | 130 | {"file", "${resource}/resources/include/constants.h"}, |
| 128 | {"template", "@@STATIC_TILING@@"}}})}, | 131 | {"template", "@@STATIC_TILING@@"}}})}, |
| @@ -170,6 +173,79 @@ NormalizedKernelSpecializationRequest CreateRequest( | |||
| 170 | return request; | 173 | return request; |
| 171 | } | 174 | } |
| 172 | 175 | ||
| 176 | +aclError BuildPlanFromManifest( | ||
| 177 | + const NormalizedKernelSpecializationRequest& request, const Json& json, const fs::path& worktree, | ||
| 178 | + const fs::path& sourceDirectory, KernelCompilationPlan& plan) | ||
| 179 | +{ | ||
| 180 | + ascendc::aclrtc::CompilationManifest manifest; | ||
| 181 | + const aclError status = ascendc::aclrtc::CompilationManifestParser(json).ParseSelected( | ||
| 182 | + request.kernelName, request.enableSuperKernel, manifest); | ||
| 183 | + if (status != ascendc::aclrtc::ACLRTC_SUCCESS) { | ||
| 184 | + return status; | ||
| 185 | + } | ||
| 186 | + return KernelCompilationPlanBuilder(request, manifest, worktree, sourceDirectory).BuildCompilationPlan(plan); | ||
| 187 | +} | ||
| 188 | + | ||
| 189 | +TEST(CompilationManifestParserTest, RepeatedSelectionsDoNotRetainPartialResults) | ||
| 190 | +{ | ||
| 191 | + const Json json = CreateManifest(); | ||
| 192 | + ascendc::aclrtc::CompilationManifestParser parser(json); | ||
| 193 | + ascendc::aclrtc::CompilationManifest manifest; | ||
| 194 | + EXPECT_EQ(parser.ParseSelected("missing", false, manifest), ascendc::aclrtc::ACLRTC_ERROR_FAILURE); | ||
| 195 | + ASSERT_EQ(parser.ParseSelected("add_custom_100000", true, manifest), ascendc::aclrtc::ACLRTC_SUCCESS); | ||
| 196 | + ASSERT_EQ(manifest.commands.size(), 3U); | ||
| 197 | + EXPECT_EQ(parser.ParseSelected("missing", false, manifest), ascendc::aclrtc::ACLRTC_ERROR_FAILURE); | ||
| 198 | + EXPECT_EQ(manifest.commands.size(), 3U); | ||
| 199 | + ASSERT_EQ(parser.ParseSelected("add_custom_100000", false, manifest), ascendc::aclrtc::ACLRTC_SUCCESS); | ||
| 200 | + EXPECT_EQ(manifest.commands.size(), 1U); | ||
| 201 | + EXPECT_EQ(manifest.constants.size(), 1U); | ||
| 202 | +} | ||
| 203 | + | ||
| 204 | +TEST(KernelCompilationPlanBuilderTest, BuildsRepeatedPlansWithoutMutatingParsedConstants) | ||
| 205 | +{ | ||
| 206 | + KernelPlanTestWorkspace workspace; | ||
| 207 | + ScopedEnvironmentVariable toolchain("ACLRTC_TEST_TOOLCHAIN", workspace.ToolchainPath().string()); | ||
| 208 | + ScopedEnvironmentVariable ascendHome("ASCEND_HOME_PATH", workspace.ToolchainPath().string()); | ||
| 209 | + const uint8_t bytes[] = {1, 2}; | ||
| 210 | + const void* addresses[] = {bytes}; | ||
| 211 | + auto request = CreateRequest(workspace, addresses, nullptr); | ||
| 212 | + ascendc::aclrtc::CompilationManifest manifest; | ||
| 213 | + const Json json = CreateManifest(); | ||
| 214 | + ASSERT_EQ( | ||
| 215 | + ascendc::aclrtc::CompilationManifestParser(json).ParseSelected( | ||
| 216 | + request.kernelName, request.enableSuperKernel, manifest), | ||
| 217 | + ascendc::aclrtc::ACLRTC_SUCCESS); | ||
| 218 | + KernelCompilationPlanBuilder builder(request, manifest, workspace.ResourcePath(), workspace.SourceDirectoryPath()); | ||
| 219 | + KernelCompilationPlan plan; | ||
| 220 | + ASSERT_EQ(builder.BuildCompilationPlan(plan), ascendc::aclrtc::ACLRTC_SUCCESS); | ||
| 221 | + ASSERT_EQ(builder.BuildCompilationPlan(plan), ascendc::aclrtc::ACLRTC_SUCCESS); | ||
| 222 | + ASSERT_EQ(plan.sourcePatches.size(), 1U); | ||
| 223 | + EXPECT_EQ(plan.sourcePatches[0].replacementText, "{0x01, 0x02}"); | ||
| 224 | + EXPECT_EQ(manifest.constants[0].GetBoundData(), nullptr); | ||
| 225 | + EXPECT_EQ(manifest.constants[0].GetBoundByteSize(), 0U); | ||
| 226 | +} | ||
| 227 | + | ||
| 228 | +TEST(CompilationManifestParserTest, OwnsSelectedFieldsWithoutResolvingRuntimeEnvironment) | ||
| 229 | +{ | ||
| 230 | + Json manifest = CreateManifest(); | ||
| 231 | + manifest["kernels"][1]["objects"][1].erase("commands"); | ||
| 232 | + manifest["options"]["unused"] = 7; | ||
| 233 | + ascendc::aclrtc::CompilationManifest spec; | ||
| 234 | + ASSERT_EQ( | ||
| 235 | + ascendc::aclrtc::CompilationManifestParser(manifest).ParseSelected("add_custom_100000", false, spec), | ||
| 236 | + ascendc::aclrtc::ACLRTC_SUCCESS); | ||
| 237 | + manifest.clear(); | ||
| 238 | + ASSERT_EQ(spec.constants.size(), 1U); | ||
| 239 | + const uint8_t byte = 0; | ||
| 240 | + const void* addresses[] = {&byte}; | ||
| 241 | + ASSERT_TRUE(spec.constants[0].BindArgument(1U, addresses, nullptr)); | ||
| 242 | + EXPECT_EQ(spec.constants[0].GetBoundByteSize(), 2U); | ||
| 243 | + ASSERT_EQ(spec.commands.size(), 1U); | ||
| 244 | + EXPECT_EQ(spec.commands[0].executable, "${env:ACLRTC_TEST_TOOLCHAIN}/bin/bisheng"); | ||
| 245 | + ASSERT_GE(spec.commands[0].arguments.size(), 3U); | ||
| 246 | + EXPECT_EQ(spec.commands[0].arguments[2], "-I${env:ACLRTC_TEST_TOOLCHAIN}/include"); | ||
| 247 | +} | ||
| 248 | + | ||
| 173 | TEST(KernelCompilationPlanBuilderTest, BuildsBasicPlanFromOnlySelectedManifestFields) | 249 | TEST(KernelCompilationPlanBuilderTest, BuildsBasicPlanFromOnlySelectedManifestFields) |
| 174 | { | 250 | { |
| 175 | KernelPlanTestWorkspace workspace; | 251 | KernelPlanTestWorkspace workspace; |
| @@ -184,9 +260,8 @@ TEST(KernelCompilationPlanBuilderTest, BuildsBasicPlanFromOnlySelectedManifestFi | |||
| 184 | 260 | ||
| 185 | KernelCompilationPlan plan; | 261 | KernelCompilationPlan plan; |
| 186 | EXPECT_EQ( | 262 | EXPECT_EQ( |
| 187 | - KernelCompilationPlanBuilder( | 263 | + BuildPlanFromManifest( |
| 188 | - request, CreateManifest(), workspace.ResourcePath(), workspace.SourceDirectoryPath()) | 264 | + request, CreateManifest(), workspace.ResourcePath(), workspace.SourceDirectoryPath(), plan), |
| 189 | - .BuildCompilationPlan(plan), | ||
| 190 | 0); | 265 | 0); |
| 191 | 266 | ||
| 192 | ASSERT_EQ(plan.sourcePatches.size(), 1U); | 267 | ASSERT_EQ(plan.sourcePatches.size(), 1U); |
| @@ -198,7 +273,7 @@ TEST(KernelCompilationPlanBuilderTest, BuildsBasicPlanFromOnlySelectedManifestFi | |||
| 198 | EXPECT_EQ(compileCommand.commandKind, CompilationCommandKind::Compile); | 273 | EXPECT_EQ(compileCommand.commandKind, CompilationCommandKind::Compile); |
| 199 | EXPECT_EQ(compileCommand.executablePath, workspace.ToolchainPath() / "bin/bisheng"); | 274 | EXPECT_EQ(compileCommand.executablePath, workspace.ToolchainPath() / "bin/bisheng"); |
| 200 | EXPECT_EQ( | 275 | EXPECT_EQ( |
| 201 | - compileCommand.commandArguments, | 276 | + compileCommand.arguments, |
| 202 | (std::vector<std::string>{ | 277 | (std::vector<std::string>{ |
| 203 | "-I", workspace.SourceDirectoryPath().string(), "-I" + (workspace.ToolchainPath() / "include").string(), | 278 | "-I", workspace.SourceDirectoryPath().string(), "-I" + (workspace.ToolchainPath() / "include").string(), |
| 204 | (workspace.ResourcePath() / "resources/src/basic.cpp").string(), "-g", "-DVALUE=1", "-o", | 279 | (workspace.ResourcePath() / "resources/src/basic.cpp").string(), "-g", "-DVALUE=1", "-o", |
| @@ -223,8 +298,7 @@ TEST(KernelCompilationPlanBuilderTest, BuildsPlanWithoutOptionalExternalSourceFi | |||
| 223 | 298 | ||
| 224 | KernelCompilationPlan plan; | 299 | KernelCompilationPlan plan; |
| 225 | EXPECT_EQ( | 300 | EXPECT_EQ( |
| 226 | - KernelCompilationPlanBuilder(request, manifest, workspace.ResourcePath(), fs::path()) | 301 | + BuildPlanFromManifest(request, manifest, workspace.ResourcePath(), fs::path(), plan), |
| 227 | - .BuildCompilationPlan(plan), | ||
| 228 | ascendc::aclrtc::ACLRTC_SUCCESS); | 302 | ascendc::aclrtc::ACLRTC_SUCCESS); |
| 229 | } | 303 | } |
| 230 | 304 | ||
| @@ -242,8 +316,7 @@ TEST(KernelCompilationPlanBuilderTest, RejectsCompileCommandWithoutOutputPath) | |||
| 242 | 316 | ||
| 243 | KernelCompilationPlan plan; | 317 | KernelCompilationPlan plan; |
| 244 | EXPECT_EQ( | 318 | EXPECT_EQ( |
| 245 | - KernelCompilationPlanBuilder(request, manifest, workspace.ResourcePath(), workspace.SourceDirectoryPath()) | 319 | + BuildPlanFromManifest(request, manifest, workspace.ResourcePath(), workspace.SourceDirectoryPath(), plan), |
| 246 | - .BuildCompilationPlan(plan), | ||
| 247 | ascendc::aclrtc::ACLRTC_ERROR_FAILURE); | 320 | ascendc::aclrtc::ACLRTC_ERROR_FAILURE); |
| 248 | } | 321 | } |
| 249 | 322 | ||
| @@ -261,8 +334,7 @@ TEST(KernelCompilationPlanBuilderTest, DoesNotTreatNonOutputOptionAsCompilerOutp | |||
| 261 | 334 | ||
| 262 | KernelCompilationPlan plan; | 335 | KernelCompilationPlan plan; |
| 263 | EXPECT_EQ( | 336 | EXPECT_EQ( |
| 264 | - KernelCompilationPlanBuilder(request, manifest, workspace.ResourcePath(), workspace.SourceDirectoryPath()) | 337 | + BuildPlanFromManifest(request, manifest, workspace.ResourcePath(), workspace.SourceDirectoryPath(), plan), |
| 265 | - .BuildCompilationPlan(plan), | ||
| 266 | ascendc::aclrtc::ACLRTC_ERROR_FAILURE); | 338 | ascendc::aclrtc::ACLRTC_ERROR_FAILURE); |
| 267 | } | 339 | } |
| 268 | 340 | ||
| @@ -280,9 +352,7 @@ TEST(KernelCompilationPlanBuilderTest, AcceptsCommandWithoutStageAndPreservesMan | |||
| 280 | 352 | ||
| 281 | KernelCompilationPlan plan; | 353 | KernelCompilationPlan plan; |
| 282 | ASSERT_EQ( | 354 | ASSERT_EQ( |
| 283 | - KernelCompilationPlanBuilder(request, manifest, workspace.ResourcePath(), workspace.SourceDirectoryPath()) | 355 | + BuildPlanFromManifest(request, manifest, workspace.ResourcePath(), workspace.SourceDirectoryPath(), plan), 0); |
| 284 | - .BuildCompilationPlan(plan), | ||
| 285 | - 0); | ||
| 286 | ASSERT_EQ(plan.compilationCommands.size(), 2U); | 356 | ASSERT_EQ(plan.compilationCommands.size(), 2U); |
| 287 | EXPECT_EQ(plan.compilationCommands[0].diagnosticLabel, "basic/compile[0]"); | 357 | EXPECT_EQ(plan.compilationCommands[0].diagnosticLabel, "basic/compile[0]"); |
| 288 | EXPECT_FALSE(plan.compilationCommands[0].parallelStage.has_value()); | 358 | EXPECT_FALSE(plan.compilationCommands[0].parallelStage.has_value()); |
| @@ -300,14 +370,13 @@ TEST(KernelCompilationPlanBuilderTest, PreservesExplicitStagesAndManifestCommand | |||
| 300 | const void* argumentAddresses[] = {tilingBytes}; | 370 | const void* argumentAddresses[] = {tilingBytes}; |
| 301 | const uint64_t argumentByteCounts[] = {sizeof(tilingBytes)}; | 371 | const uint64_t argumentByteCounts[] = {sizeof(tilingBytes)}; |
| 302 | NormalizedKernelSpecializationRequest request = CreateRequest(workspace, argumentAddresses, argumentByteCounts); | 372 | NormalizedKernelSpecializationRequest request = CreateRequest(workspace, argumentAddresses, argumentByteCounts); |
| 303 | - request.compilationVariant = KernelCompilationVariant::BasicWithSuperKernel; | 373 | + request.enableSuperKernel = true; |
| 304 | request.compilerOptions.superKernelOptions = {"-g"}; | 374 | request.compilerOptions.superKernelOptions = {"-g"}; |
| 305 | 375 | ||
| 306 | KernelCompilationPlan plan; | 376 | KernelCompilationPlan plan; |
| 307 | ASSERT_EQ( | 377 | ASSERT_EQ( |
| 308 | - KernelCompilationPlanBuilder( | 378 | + BuildPlanFromManifest( |
| 309 | - request, CreateManifest(), workspace.ResourcePath(), workspace.SourceDirectoryPath()) | 379 | + request, CreateManifest(), workspace.ResourcePath(), workspace.SourceDirectoryPath(), plan), |
| 310 | - .BuildCompilationPlan(plan), | ||
| 311 | 0); | 380 | 0); |
| 312 | ASSERT_EQ(plan.compilationCommands.size(), 4U); | 381 | ASSERT_EQ(plan.compilationCommands.size(), 4U); |
| 313 | EXPECT_EQ(plan.compilationCommands[0].diagnosticLabel, "basic/compile[0]"); | 382 | EXPECT_EQ(plan.compilationCommands[0].diagnosticLabel, "basic/compile[0]"); |
| @@ -319,10 +388,8 @@ TEST(KernelCompilationPlanBuilderTest, PreservesExplicitStagesAndManifestCommand | |||
| 319 | EXPECT_EQ(plan.compilationCommands[2].parallelStage, 1U); | 388 | EXPECT_EQ(plan.compilationCommands[2].parallelStage, 1U); |
| 320 | EXPECT_FALSE(plan.compilationCommands[3].parallelStage.has_value()); | 389 | EXPECT_FALSE(plan.compilationCommands[3].parallelStage.has_value()); |
| 321 | EXPECT_NE( | 390 | EXPECT_NE( |
| 322 | - std::find( | 391 | + std::find(plan.compilationCommands[1].arguments.begin(), plan.compilationCommands[1].arguments.end(), "-g"), |
| 323 | - plan.compilationCommands[1].commandArguments.begin(), plan.compilationCommands[1].commandArguments.end(), | 392 | + plan.compilationCommands[1].arguments.end()); |
| 324 | - "-g"), | ||
| 325 | - plan.compilationCommands[1].commandArguments.end()); | ||
| 326 | } | 393 | } |
| 327 | 394 | ||
| 328 | TEST(KernelCompilationPlanBuilderTest, SelectsAllRequestedObjectsInManifestOrder) | 395 | TEST(KernelCompilationPlanBuilderTest, SelectsAllRequestedObjectsInManifestOrder) |
| @@ -335,7 +402,7 @@ TEST(KernelCompilationPlanBuilderTest, SelectsAllRequestedObjectsInManifestOrder | |||
| 335 | const void* argumentAddresses[] = {tilingBytes}; | 402 | const void* argumentAddresses[] = {tilingBytes}; |
| 336 | const uint64_t argumentByteCounts[] = {sizeof(tilingBytes)}; | 403 | const uint64_t argumentByteCounts[] = {sizeof(tilingBytes)}; |
| 337 | NormalizedKernelSpecializationRequest request = CreateRequest(workspace, argumentAddresses, argumentByteCounts); | 404 | NormalizedKernelSpecializationRequest request = CreateRequest(workspace, argumentAddresses, argumentByteCounts); |
| 338 | - request.compilationVariant = KernelCompilationVariant::BasicWithSuperKernel; | 405 | + request.enableSuperKernel = true; |
| 339 | 406 | ||
| 340 | Json manifest = CreateManifest(); | 407 | Json manifest = CreateManifest(); |
| 341 | Json secondBasicObject = manifest["kernels"][1]["objects"][0]; | 408 | Json secondBasicObject = manifest["kernels"][1]["objects"][0]; |
| @@ -354,9 +421,7 @@ TEST(KernelCompilationPlanBuilderTest, SelectsAllRequestedObjectsInManifestOrder | |||
| 354 | 421 | ||
| 355 | KernelCompilationPlan plan; | 422 | KernelCompilationPlan plan; |
| 356 | ASSERT_EQ( | 423 | ASSERT_EQ( |
| 357 | - KernelCompilationPlanBuilder(request, manifest, workspace.ResourcePath(), workspace.SourceDirectoryPath()) | 424 | + BuildPlanFromManifest(request, manifest, workspace.ResourcePath(), workspace.SourceDirectoryPath(), plan), 0); |
| 358 | - .BuildCompilationPlan(plan), | ||
| 359 | - 0); | ||
| 360 | 425 | ||
| 361 | ASSERT_EQ(plan.compilationCommands.size(), 7U); | 426 | ASSERT_EQ(plan.compilationCommands.size(), 7U); |
| 362 | EXPECT_EQ(plan.compilationCommands[0].diagnosticLabel, "basic/compile[0]"); | 427 | EXPECT_EQ(plan.compilationCommands[0].diagnosticLabel, "basic/compile[0]"); |
| @@ -367,7 +432,7 @@ TEST(KernelCompilationPlanBuilderTest, SelectsAllRequestedObjectsInManifestOrder | |||
| 367 | EXPECT_EQ(plan.compilationCommands[5].diagnosticLabel, "sk_aux/objcopy[1]"); | 432 | EXPECT_EQ(plan.compilationCommands[5].diagnosticLabel, "sk_aux/objcopy[1]"); |
| 368 | EXPECT_EQ(plan.compilationCommands[6].diagnosticLabel, "link"); | 433 | EXPECT_EQ(plan.compilationCommands[6].diagnosticLabel, "link"); |
| 369 | 434 | ||
| 370 | - const std::vector<std::string>& linkArguments = plan.compilationCommands.back().commandArguments; | 435 | + const std::vector<std::string>& linkArguments = plan.compilationCommands.back().arguments; |
| 371 | EXPECT_NE( | 436 | EXPECT_NE( |
| 372 | std::find( | 437 | std::find( |
| 373 | linkArguments.begin(), linkArguments.end(), | 438 | linkArguments.begin(), linkArguments.end(), |
| @@ -393,16 +458,14 @@ TEST(KernelCompilationPlanBuilderTest, RequiresOnlyEnvironmentUsedBySelectedObje | |||
| 393 | 458 | ||
| 394 | KernelCompilationPlan plan; | 459 | KernelCompilationPlan plan; |
| 395 | EXPECT_EQ( | 460 | EXPECT_EQ( |
| 396 | - KernelCompilationPlanBuilder( | 461 | + BuildPlanFromManifest( |
| 397 | - request, CreateManifest(), workspace.ResourcePath(), workspace.SourceDirectoryPath()) | 462 | + request, CreateManifest(), workspace.ResourcePath(), workspace.SourceDirectoryPath(), plan), |
| 398 | - .BuildCompilationPlan(plan), | ||
| 399 | 0); | 463 | 0); |
| 400 | 464 | ||
| 401 | - request.compilationVariant = KernelCompilationVariant::BasicWithSuperKernel; | 465 | + request.enableSuperKernel = true; |
| 402 | EXPECT_EQ( | 466 | EXPECT_EQ( |
| 403 | - KernelCompilationPlanBuilder( | 467 | + BuildPlanFromManifest( |
| 404 | - request, CreateManifest(), workspace.ResourcePath(), workspace.SourceDirectoryPath()) | 468 | + request, CreateManifest(), workspace.ResourcePath(), workspace.SourceDirectoryPath(), plan), |
| 405 | - .BuildCompilationPlan(plan), | ||
| 406 | ascendc::aclrtc::ACLRTC_ERROR_FAILURE); | 469 | ascendc::aclrtc::ACLRTC_ERROR_FAILURE); |
| 407 | } | 470 | } |
| 408 | 471 | ||
| @@ -421,17 +484,16 @@ TEST(KernelCompilationPlanBuilderTest, RejectsMalformedEnvironmentPlaceholders) | |||
| 421 | manifestWithUnterminatedPlaceholder["kernels"][1]["objects"][0]["commands"][0]["cmd"][2] = | 484 | manifestWithUnterminatedPlaceholder["kernels"][1]["objects"][0]["commands"][0]["cmd"][2] = |
| 422 | "${env:ACLRTC_TEST_TOOLCHAIN"; | 485 | "${env:ACLRTC_TEST_TOOLCHAIN"; |
| 423 | EXPECT_EQ( | 486 | EXPECT_EQ( |
| 424 | - KernelCompilationPlanBuilder( | 487 | + BuildPlanFromManifest( |
| 425 | - request, manifestWithUnterminatedPlaceholder, workspace.ResourcePath(), workspace.SourceDirectoryPath()) | 488 | + request, manifestWithUnterminatedPlaceholder, workspace.ResourcePath(), workspace.SourceDirectoryPath(), |
| 426 | - .BuildCompilationPlan(plan), | 489 | + plan), |
| 427 | ascendc::aclrtc::ACLRTC_ERROR_FAILURE); | 490 | ascendc::aclrtc::ACLRTC_ERROR_FAILURE); |
| 428 | 491 | ||
| 429 | Json manifestWithEmptyEnvironmentName = CreateManifest(); | 492 | Json manifestWithEmptyEnvironmentName = CreateManifest(); |
| 430 | manifestWithEmptyEnvironmentName["kernels"][1]["objects"][0]["commands"][0]["cmd"][2] = "${env:}"; | 493 | manifestWithEmptyEnvironmentName["kernels"][1]["objects"][0]["commands"][0]["cmd"][2] = "${env:}"; |
| 431 | EXPECT_EQ( | 494 | EXPECT_EQ( |
| 432 | - KernelCompilationPlanBuilder( | 495 | + BuildPlanFromManifest( |
| 433 | - request, manifestWithEmptyEnvironmentName, workspace.ResourcePath(), workspace.SourceDirectoryPath()) | 496 | + request, manifestWithEmptyEnvironmentName, workspace.ResourcePath(), workspace.SourceDirectoryPath(), plan), |
| 434 | - .BuildCompilationPlan(plan), | ||
| 435 | ascendc::aclrtc::ACLRTC_ERROR_FAILURE); | 497 | ascendc::aclrtc::ACLRTC_ERROR_FAILURE); |
| 436 | } | 498 | } |
| 437 | 499 | ||
| @@ -449,8 +511,7 @@ TEST(KernelCompilationPlanBuilderTest, RejectsUndefinedOptionReference) | |||
| 449 | 511 | ||
| 450 | KernelCompilationPlan plan; | 512 | KernelCompilationPlan plan; |
| 451 | EXPECT_EQ( | 513 | EXPECT_EQ( |
| 452 | - KernelCompilationPlanBuilder(request, manifest, workspace.ResourcePath(), workspace.SourceDirectoryPath()) | 514 | + BuildPlanFromManifest(request, manifest, workspace.ResourcePath(), workspace.SourceDirectoryPath(), plan), |
| 453 | - .BuildCompilationPlan(plan), | ||
| 454 | ascendc::aclrtc::ACLRTC_ERROR_FAILURE); | 515 | ascendc::aclrtc::ACLRTC_ERROR_FAILURE); |
| 455 | } | 516 | } |
| 456 | 517 | ||
| @@ -470,16 +531,10 @@ TEST(KernelCompilationPlanBuilderTest, DoesNotRecursivelyExpandEnvironmentOrUser | |||
| 470 | 531 | ||
| 471 | KernelCompilationPlan plan; | 532 | KernelCompilationPlan plan; |
| 472 | ASSERT_EQ( | 533 | ASSERT_EQ( |
| 473 | - KernelCompilationPlanBuilder(request, manifest, workspace.ResourcePath(), workspace.SourceDirectoryPath()) | 534 | + BuildPlanFromManifest(request, manifest, workspace.ResourcePath(), workspace.SourceDirectoryPath(), plan), 0); |
| 474 | - .BuildCompilationPlan(plan), | 535 | + const std::vector<std::string>& arguments = plan.compilationCommands.front().arguments; |
| 475 | - 0); | 536 | + EXPECT_NE(std::find(arguments.begin(), arguments.end(), "${options:not_reexpanded}"), arguments.end()); |
| 476 | - const std::vector<std::string>& commandArguments = plan.compilationCommands.front().commandArguments; | 537 | + EXPECT_NE(std::find(arguments.begin(), arguments.end(), "${env:USER_OPTION_STAYS_LITERAL}"), arguments.end()); |
| 477 | - EXPECT_NE( | ||
| 478 | - std::find(commandArguments.begin(), commandArguments.end(), "${options:not_reexpanded}"), | ||
| 479 | - commandArguments.end()); | ||
| 480 | - EXPECT_NE( | ||
| 481 | - std::find(commandArguments.begin(), commandArguments.end(), "${env:USER_OPTION_STAYS_LITERAL}"), | ||
| 482 | - commandArguments.end()); | ||
| 483 | } | 538 | } |
| 484 | 539 | ||
| 485 | TEST(KernelCompilationPlanBuilderTest, AcceptsKernelWithoutLinkOptions) | 540 | TEST(KernelCompilationPlanBuilderTest, AcceptsKernelWithoutLinkOptions) |
| @@ -496,9 +551,7 @@ TEST(KernelCompilationPlanBuilderTest, AcceptsKernelWithoutLinkOptions) | |||
| 496 | 551 | ||
| 497 | KernelCompilationPlan plan; | 552 | KernelCompilationPlan plan; |
| 498 | EXPECT_EQ( | 553 | EXPECT_EQ( |
| 499 | - KernelCompilationPlanBuilder(request, manifest, workspace.ResourcePath(), workspace.SourceDirectoryPath()) | 554 | + BuildPlanFromManifest(request, manifest, workspace.ResourcePath(), workspace.SourceDirectoryPath(), plan), 0); |
| 500 | - .BuildCompilationPlan(plan), | ||
| 501 | - 0); | ||
| 502 | EXPECT_EQ(plan.sourcePatches.size(), 1U); | 555 | EXPECT_EQ(plan.sourcePatches.size(), 1U); |
| 503 | ASSERT_EQ(plan.compilationCommands.size(), 2U); | 556 | ASSERT_EQ(plan.compilationCommands.size(), 2U); |
| 504 | EXPECT_EQ(plan.compilationCommands.back().commandKind, CompilationCommandKind::Link); | 557 | EXPECT_EQ(plan.compilationCommands.back().commandKind, CompilationCommandKind::Link); |
| @@ -515,17 +568,15 @@ TEST(KernelCompilationPlanBuilderTest, RejectsKernelWithoutStaticConstants) | |||
| 515 | Json manifestWithoutConstants = CreateManifest(); | 568 | Json manifestWithoutConstants = CreateManifest(); |
| 516 | manifestWithoutConstants["kernels"][1].erase("constant_infos"); | 569 | manifestWithoutConstants["kernels"][1].erase("constant_infos"); |
| 517 | EXPECT_EQ( | 570 | EXPECT_EQ( |
| 518 | - KernelCompilationPlanBuilder( | 571 | + BuildPlanFromManifest( |
| 519 | - request, manifestWithoutConstants, workspace.ResourcePath(), workspace.SourceDirectoryPath()) | 572 | + request, manifestWithoutConstants, workspace.ResourcePath(), workspace.SourceDirectoryPath(), plan), |
| 520 | - .BuildCompilationPlan(plan), | ||
| 521 | ascendc::aclrtc::ACLRTC_ERROR_FAILURE); | 573 | ascendc::aclrtc::ACLRTC_ERROR_FAILURE); |
| 522 | 574 | ||
| 523 | Json manifestWithEmptyConstants = CreateManifest(); | 575 | Json manifestWithEmptyConstants = CreateManifest(); |
| 524 | manifestWithEmptyConstants["kernels"][1]["constant_infos"] = Json::array(); | 576 | manifestWithEmptyConstants["kernels"][1]["constant_infos"] = Json::array(); |
| 525 | EXPECT_EQ( | 577 | EXPECT_EQ( |
| 526 | - KernelCompilationPlanBuilder( | 578 | + BuildPlanFromManifest( |
| 527 | - request, manifestWithEmptyConstants, workspace.ResourcePath(), workspace.SourceDirectoryPath()) | 579 | + request, manifestWithEmptyConstants, workspace.ResourcePath(), workspace.SourceDirectoryPath(), plan), |
| 528 | - .BuildCompilationPlan(plan), | ||
| 529 | ascendc::aclrtc::ACLRTC_ERROR_FAILURE); | 580 | ascendc::aclrtc::ACLRTC_ERROR_FAILURE); |
| 530 | } | 581 | } |
| 531 | 582 | ||
| @@ -538,28 +589,144 @@ TEST(KernelCompilationPlanBuilderTest, RejectsMissingRuntimeConstantBuffer) | |||
| 538 | 589 | ||
| 539 | KernelCompilationPlan plan; | 590 | KernelCompilationPlan plan; |
| 540 | EXPECT_EQ( | 591 | EXPECT_EQ( |
| 541 | - KernelCompilationPlanBuilder( | 592 | + BuildPlanFromManifest( |
| 542 | - request, CreateManifest(), workspace.ResourcePath(), workspace.SourceDirectoryPath()) | 593 | + request, CreateManifest(), workspace.ResourcePath(), workspace.SourceDirectoryPath(), plan), |
| 543 | - .BuildCompilationPlan(plan), | ||
| 544 | ascendc::aclrtc::ACLRTC_ERROR_INVALID_INPUT); | 594 | ascendc::aclrtc::ACLRTC_ERROR_INVALID_INPUT); |
| 545 | } | 595 | } |
| 546 | 596 | ||
| 547 | -TEST(KernelCompilationPlanBuilderTest, RejectsMismatchedRuntimeConstantByteCount) | 597 | +TEST(KernelCompilationPlanBuilderTest, PointerConstantUsesManifestByteSize) |
| 548 | { | 598 | { |
| 549 | KernelPlanTestWorkspace workspace; | 599 | KernelPlanTestWorkspace workspace; |
| 550 | ScopedEnvironmentVariable toolchainEnvironment("ACLRTC_TEST_TOOLCHAIN", workspace.ToolchainPath().string()); | 600 | ScopedEnvironmentVariable toolchainEnvironment("ACLRTC_TEST_TOOLCHAIN", workspace.ToolchainPath().string()); |
| 551 | ScopedEnvironmentVariable ascendHomeEnvironment("ASCEND_HOME_PATH", workspace.ToolchainPath().string()); | 601 | ScopedEnvironmentVariable ascendHomeEnvironment("ASCEND_HOME_PATH", workspace.ToolchainPath().string()); |
| 552 | - const uint8_t oversizedTilingBytes[] = {0x01, 0x02, 0x03}; | 602 | + const uint8_t tilingBytes[] = {0x01, 0x02, 0x03}; |
| 553 | - const void* argumentDataPointers[] = {oversizedTilingBytes}; | 603 | + const void* argumentDataPointers[] = {tilingBytes}; |
| 554 | - const uint64_t argumentByteCounts[] = {sizeof(oversizedTilingBytes)}; | 604 | + NormalizedKernelSpecializationRequest request = CreateRequest(workspace, argumentDataPointers, nullptr); |
| 555 | - NormalizedKernelSpecializationRequest request = CreateRequest(workspace, argumentDataPointers, argumentByteCounts); | ||
| 556 | 605 | ||
| 557 | KernelCompilationPlan plan; | 606 | KernelCompilationPlan plan; |
| 558 | EXPECT_EQ( | 607 | EXPECT_EQ( |
| 559 | - KernelCompilationPlanBuilder( | 608 | + BuildPlanFromManifest( |
| 560 | - request, CreateManifest(), workspace.ResourcePath(), workspace.SourceDirectoryPath()) | 609 | + request, CreateManifest(), workspace.ResourcePath(), workspace.SourceDirectoryPath(), plan), |
| 561 | - .BuildCompilationPlan(plan), | 610 | + ascendc::aclrtc::ACLRTC_SUCCESS); |
| 562 | - ascendc::aclrtc::ACLRTC_ERROR_INVALID_INPUT); | 611 | + ASSERT_EQ(plan.sourcePatches.size(), 1U); |
| 612 | + EXPECT_EQ(plan.sourcePatches[0].replacementText, "{0x01, 0x02}"); | ||
| 613 | +} | ||
| 614 | + | ||
| 615 | +TEST(KernelCompilationPlanBuilderTest, DefaultStructConstantUsesArgumentByteSize) | ||
| 616 | +{ | ||
| 617 | + KernelPlanTestWorkspace workspace; | ||
| 618 | + ScopedEnvironmentVariable toolchainEnvironment("ACLRTC_TEST_TOOLCHAIN", workspace.ToolchainPath().string()); | ||
| 619 | + ScopedEnvironmentVariable ascendHomeEnvironment("ASCEND_HOME_PATH", workspace.ToolchainPath().string()); | ||
| 620 | + const uint8_t tilingBytes[] = {0x01, 0x02, 0x03}; | ||
| 621 | + const void* argumentDataPointers[] = {tilingBytes}; | ||
| 622 | + const uint64_t argumentByteCounts[] = {sizeof(tilingBytes)}; | ||
| 623 | + NormalizedKernelSpecializationRequest request = CreateRequest(workspace, argumentDataPointers, argumentByteCounts); | ||
| 624 | + Json manifest = CreateManifest(); | ||
| 625 | + manifest["kernels"][1]["constant_infos"][0].erase("arg_type"); | ||
| 626 | + manifest["kernels"][1]["constant_infos"][0].erase("byte_size"); | ||
| 627 | + | ||
| 628 | + KernelCompilationPlan plan; | ||
| 629 | + EXPECT_EQ( | ||
| 630 | + BuildPlanFromManifest(request, manifest, workspace.ResourcePath(), workspace.SourceDirectoryPath(), plan), | ||
| 631 | + ascendc::aclrtc::ACLRTC_SUCCESS); | ||
| 632 | + ASSERT_EQ(plan.sourcePatches.size(), 1U); | ||
| 633 | + EXPECT_EQ(plan.sourcePatches[0].replacementText, "{0x01, 0x02, 0x03}"); | ||
| 634 | +} | ||
| 635 | + | ||
| 636 | +TEST(KernelCompilationPlanBuilderTest, RejectsStructConstantWithManifestByteSize) | ||
| 637 | +{ | ||
| 638 | + KernelPlanTestWorkspace workspace; | ||
| 639 | + ScopedEnvironmentVariable toolchainEnvironment("ACLRTC_TEST_TOOLCHAIN", workspace.ToolchainPath().string()); | ||
| 640 | + ScopedEnvironmentVariable ascendHomeEnvironment("ASCEND_HOME_PATH", workspace.ToolchainPath().string()); | ||
| 641 | + const uint8_t tilingBytes[] = {0x01, 0x02, 0x03}; | ||
| 642 | + const void* argumentDataPointers[] = {tilingBytes}; | ||
| 643 | + const uint64_t argumentByteCounts[] = {sizeof(tilingBytes)}; | ||
| 644 | + NormalizedKernelSpecializationRequest request = CreateRequest(workspace, argumentDataPointers, argumentByteCounts); | ||
| 645 | + Json manifest = CreateManifest(); | ||
| 646 | + manifest["kernels"][1]["constant_infos"][0]["arg_type"] = "struct"; | ||
| 647 | + | ||
| 648 | + KernelCompilationPlan plan; | ||
| 649 | + EXPECT_EQ( | ||
| 650 | + BuildPlanFromManifest(request, manifest, workspace.ResourcePath(), workspace.SourceDirectoryPath(), plan), | ||
| 651 | + ascendc::aclrtc::ACLRTC_ERROR_FAILURE); | ||
| 652 | + manifest["kernels"][1]["constant_infos"][0].erase("arg_type"); | ||
| 653 | + EXPECT_EQ( | ||
| 654 | + BuildPlanFromManifest(request, manifest, workspace.ResourcePath(), workspace.SourceDirectoryPath(), plan), | ||
| 655 | + ascendc::aclrtc::ACLRTC_ERROR_FAILURE); | ||
| 656 | + EXPECT_TRUE(plan.sourcePatches.empty()); | ||
| 657 | +} | ||
| 658 | + | ||
| 659 | +TEST(KernelCompilationPlanBuilderTest, RejectsInvalidInputsBeforeReadingAnyConstantBytes) | ||
| 660 | +{ | ||
| 661 | + KernelPlanTestWorkspace workspace; | ||
| 662 | + ScopedEnvironmentVariable toolchainEnvironment("ACLRTC_TEST_TOOLCHAIN", workspace.ToolchainPath().string()); | ||
| 663 | + ScopedEnvironmentVariable ascendHomeEnvironment("ASCEND_HOME_PATH", workspace.ToolchainPath().string()); | ||
| 664 | + for (int invalidInputKind : {0, 1, 2}) { | ||
| 665 | + // A protected buffer detects reads before the remaining inputs have been checked. | ||
| 666 | + ASSERT_EXIT( | ||
| 667 | + { | ||
| 668 | + const size_t pageSize = static_cast<size_t>(sysconf(_SC_PAGESIZE)); | ||
| 669 | + void* unreadable = mmap(nullptr, pageSize, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); | ||
| 670 | + if (unreadable == MAP_FAILED) { | ||
| 671 | + _exit(2); | ||
| 672 | + } | ||
| 673 | + const void* addresses[] = {unreadable}; | ||
| 674 | + const uint64_t sizes[] = {2U}; | ||
| 675 | + auto request = CreateRequest(workspace, addresses, sizes); | ||
| 676 | + Json manifest = CreateManifest(); | ||
| 677 | + auto& kernel = manifest["kernels"][1]; | ||
| 678 | + if (invalidInputKind == 0) { | ||
| 679 | + Json constant = kernel["constant_infos"][0]; | ||
| 680 | + constant["parameter_index"] = 1U; | ||
| 681 | + kernel["constant_infos"].push_back(constant); | ||
| 682 | + } else if (invalidInputKind == 1) { | ||
| 683 | + kernel["objects"][0]["commands"][0]["cmd"][0] = "/aclrtc-test-missing-compiler"; | ||
| 684 | + } else { | ||
| 685 | + unsetenv("ACLRTC_TEST_MISSING_LINK_OPTION"); | ||
| 686 | + kernel["link_options"] = Json::array({"${env:ACLRTC_TEST_MISSING_LINK_OPTION}"}); | ||
| 687 | + } | ||
| 688 | + KernelCompilationPlan plan; | ||
| 689 | + plan.linkedKernelElfPath = "unchanged.elf"; | ||
| 690 | + const auto status = BuildPlanFromManifest( | ||
| 691 | + request, manifest, workspace.ResourcePath(), workspace.SourceDirectoryPath(), plan); | ||
| 692 | + const auto expected = invalidInputKind == 0 ? ascendc::aclrtc::ACLRTC_ERROR_INVALID_INPUT : | ||
| 693 | + ascendc::aclrtc::ACLRTC_ERROR_FAILURE; | ||
| 694 | + munmap(unreadable, pageSize); | ||
| 695 | + _exit(status == expected && plan.linkedKernelElfPath == "unchanged.elf" ? 0 : 1); | ||
| 696 | + }, | ||
| 697 | + ::testing::ExitedWithCode(0), ""); | ||
| 698 | + } | ||
| 699 | +} | ||
| 700 | + | ||
| 701 | +TEST(KernelCompilationPlanBuilderTest, BuildsMixedConstantsUsingEachParameterIndexAndSizeSource) | ||
| 702 | +{ | ||
| 703 | + KernelPlanTestWorkspace workspace; | ||
| 704 | + ScopedEnvironmentVariable toolchainEnvironment("ACLRTC_TEST_TOOLCHAIN", workspace.ToolchainPath().string()); | ||
| 705 | + ScopedEnvironmentVariable ascendHomeEnvironment("ASCEND_HOME_PATH", workspace.ToolchainPath().string()); | ||
| 706 | + const uint8_t pointerBytes[] = {0x01, 0x02, 0x03}; | ||
| 707 | + const uint8_t structBytes[] = {0xfe, 0xff, 0x04}; | ||
| 708 | + const void* addresses[] = {nullptr, pointerBytes, structBytes}; | ||
| 709 | + const uint64_t sizes[] = {0U, sizeof(void*), sizeof(structBytes)}; | ||
| 710 | + auto request = CreateRequest(workspace, addresses, sizes); | ||
| 711 | + request.kernelArgumentCount = 3U; | ||
| 712 | + Json manifest = CreateManifest(); | ||
| 713 | + auto& constants = manifest["kernels"][1]["constant_infos"]; | ||
| 714 | + constants[0]["parameter_index"] = 1U; | ||
| 715 | + Json structConstant = constants[0]; | ||
| 716 | + structConstant["parameter_index"] = 2U; | ||
| 717 | + structConstant["arg_type"] = "struct"; | ||
| 718 | + structConstant.erase("byte_size"); | ||
| 719 | + structConstant["template"] = "@@STRUCT@@"; | ||
| 720 | + constants.push_back(structConstant); | ||
| 721 | + | ||
| 722 | + KernelCompilationPlan plan; | ||
| 723 | + ASSERT_EQ( | ||
| 724 | + BuildPlanFromManifest(request, manifest, workspace.ResourcePath(), workspace.SourceDirectoryPath(), plan), | ||
| 725 | + ascendc::aclrtc::ACLRTC_SUCCESS); | ||
| 726 | + ASSERT_EQ(plan.sourcePatches.size(), 2U); | ||
| 727 | + EXPECT_EQ(plan.sourcePatches[0].replacementText, "{0x01, 0x02}"); | ||
| 728 | + EXPECT_EQ(plan.sourcePatches[1].replacementText, "{0xfe, 0xff, 0x04}"); | ||
| 729 | + EXPECT_EQ(plan.sourcePatches[1].templateText, "@@STRUCT@@"); | ||
| 563 | } | 730 | } |
| 564 | 731 | ||
| 565 | TEST(KernelCompilationPlanBuilderTest, RejectsMissingResourceWorktree) | 732 | TEST(KernelCompilationPlanBuilderTest, RejectsMissingResourceWorktree) |
| @@ -574,41 +741,11 @@ TEST(KernelCompilationPlanBuilderTest, RejectsMissingResourceWorktree) | |||
| 574 | 741 | ||
| 575 | const fs::path missingWorktreePath = workspace.ResourcePath() / "missing"; | 742 | const fs::path missingWorktreePath = workspace.ResourcePath() / "missing"; |
| 576 | EXPECT_EQ( | 743 | EXPECT_EQ( |
| 577 | - KernelCompilationPlanBuilder(request, CreateManifest(), missingWorktreePath, workspace.SourceDirectoryPath()) | 744 | + BuildPlanFromManifest(request, CreateManifest(), missingWorktreePath, workspace.SourceDirectoryPath(), plan), |
| 578 | - .BuildCompilationPlan(plan), | ||
| 579 | ascendc::aclrtc::ACLRTC_ERROR_FAILURE); | 745 | ascendc::aclrtc::ACLRTC_ERROR_FAILURE); |
| 580 | } | 746 | } |
| 581 | 747 | ||
| 582 | -TEST(KernelCompilationPlanBuilderTest, RejectsInvalidRuntimeConstantLocations) | 748 | +TEST(KernelCompilationPlanBuilderTest, ExpandsCommandPrefixAndRejectsInvalidCommands) |
| 583 | -{ | ||
| 584 | - KernelPlanTestWorkspace workspace; | ||
| 585 | - ScopedEnvironmentVariable toolchainEnvironment("ACLRTC_TEST_TOOLCHAIN", workspace.ToolchainPath().string()); | ||
| 586 | - ScopedEnvironmentVariable ascendHomeEnvironment("ASCEND_HOME_PATH", workspace.ToolchainPath().string()); | ||
| 587 | - const uint8_t constantBytes[] = {0x01, 0x02}; | ||
| 588 | - const void* validArgumentDataPointers[] = {constantBytes}; | ||
| 589 | - const void* nullArgumentDataPointers[] = {nullptr}; | ||
| 590 | - const uint64_t argumentByteCounts[] = {sizeof(constantBytes)}; | ||
| 591 | - KernelCompilationPlan plan; | ||
| 592 | - | ||
| 593 | - Json outOfRangeManifest = CreateManifest(); | ||
| 594 | - outOfRangeManifest["kernels"][1]["constant_infos"][0]["parameter_index"] = 1U; | ||
| 595 | - NormalizedKernelSpecializationRequest request = | ||
| 596 | - CreateRequest(workspace, validArgumentDataPointers, argumentByteCounts); | ||
| 597 | - EXPECT_EQ( | ||
| 598 | - KernelCompilationPlanBuilder( | ||
| 599 | - request, outOfRangeManifest, workspace.ResourcePath(), workspace.SourceDirectoryPath()) | ||
| 600 | - .BuildCompilationPlan(plan), | ||
| 601 | - ascendc::aclrtc::ACLRTC_ERROR_INVALID_INPUT); | ||
| 602 | - | ||
| 603 | - request = CreateRequest(workspace, nullArgumentDataPointers, argumentByteCounts); | ||
| 604 | - EXPECT_EQ( | ||
| 605 | - KernelCompilationPlanBuilder( | ||
| 606 | - request, CreateManifest(), workspace.ResourcePath(), workspace.SourceDirectoryPath()) | ||
| 607 | - .BuildCompilationPlan(plan), | ||
| 608 | - ascendc::aclrtc::ACLRTC_ERROR_INVALID_INPUT); | ||
| 609 | -} | ||
| 610 | - | ||
| 611 | -TEST(KernelCompilationPlanBuilderTest, RejectsMalformedManifestCommands) | ||
| 612 | { | 749 | { |
| 613 | KernelPlanTestWorkspace workspace; | 750 | KernelPlanTestWorkspace workspace; |
| 614 | ScopedEnvironmentVariable toolchainEnvironment("ACLRTC_TEST_TOOLCHAIN", workspace.ToolchainPath().string()); | 751 | ScopedEnvironmentVariable toolchainEnvironment("ACLRTC_TEST_TOOLCHAIN", workspace.ToolchainPath().string()); |
| @@ -623,37 +760,56 @@ TEST(KernelCompilationPlanBuilderTest, RejectsMalformedManifestCommands) | |||
| 623 | Json unsupportedCommandManifest = CreateManifest(); | 760 | Json unsupportedCommandManifest = CreateManifest(); |
| 624 | unsupportedCommandManifest["kernels"][1]["objects"][0]["commands"][0]["type"] = "future-command"; | 761 | unsupportedCommandManifest["kernels"][1]["objects"][0]["commands"][0]["type"] = "future-command"; |
| 625 | EXPECT_EQ( | 762 | EXPECT_EQ( |
| 626 | - KernelCompilationPlanBuilder( | 763 | + BuildPlanFromManifest( |
| 627 | - request, unsupportedCommandManifest, workspace.ResourcePath(), workspace.SourceDirectoryPath()) | 764 | + request, unsupportedCommandManifest, workspace.ResourcePath(), workspace.SourceDirectoryPath(), plan), |
| 628 | - .BuildCompilationPlan(plan), | ||
| 629 | ascendc::aclrtc::ACLRTC_ERROR_FAILURE); | 765 | ascendc::aclrtc::ACLRTC_ERROR_FAILURE); |
| 630 | 766 | ||
| 631 | Json emptyCommandManifest = CreateManifest(); | 767 | Json emptyCommandManifest = CreateManifest(); |
| 632 | emptyCommandManifest["kernels"][1]["objects"][0]["commands"][0]["cmd"] = Json::array(); | 768 | emptyCommandManifest["kernels"][1]["objects"][0]["commands"][0]["cmd"] = Json::array(); |
| 633 | EXPECT_EQ( | 769 | EXPECT_EQ( |
| 634 | - KernelCompilationPlanBuilder( | 770 | + BuildPlanFromManifest( |
| 635 | - request, emptyCommandManifest, workspace.ResourcePath(), workspace.SourceDirectoryPath()) | 771 | + request, emptyCommandManifest, workspace.ResourcePath(), workspace.SourceDirectoryPath(), plan), |
| 636 | - .BuildCompilationPlan(plan), | ||
| 637 | ascendc::aclrtc::ACLRTC_ERROR_FAILURE); | 772 | ascendc::aclrtc::ACLRTC_ERROR_FAILURE); |
| 638 | 773 | ||
| 639 | Json expandedExecutableManifest = CreateManifest(); | 774 | Json expandedExecutableManifest = CreateManifest(); |
| 640 | - expandedExecutableManifest["kernels"][1]["objects"][0]["commands"][0]["cmd"][0] = "${options:common_compile}"; | 775 | + expandedExecutableManifest["options"]["common_compile"] = Json::array(); |
| 776 | + expandedExecutableManifest["kernels"][1]["objects"][0]["commands"][0]["cmd"] = | ||
| 777 | + Json::array({"${options:common_compile}"}); | ||
| 641 | EXPECT_EQ( | 778 | EXPECT_EQ( |
| 642 | - KernelCompilationPlanBuilder( | 779 | + BuildPlanFromManifest( |
| 643 | - request, expandedExecutableManifest, workspace.ResourcePath(), workspace.SourceDirectoryPath()) | 780 | + request, expandedExecutableManifest, workspace.ResourcePath(), workspace.SourceDirectoryPath(), plan), |
| 644 | - .BuildCompilationPlan(plan), | ||
| 645 | ascendc::aclrtc::ACLRTC_ERROR_FAILURE); | 781 | ascendc::aclrtc::ACLRTC_ERROR_FAILURE); |
| 646 | 782 | ||
| 783 | + KernelCompilationPlan expectedPlan; | ||
| 784 | + ASSERT_EQ( | ||
| 785 | + BuildPlanFromManifest( | ||
| 786 | + request, CreateManifest(), workspace.ResourcePath(), workspace.SourceDirectoryPath(), expectedPlan), | ||
| 787 | + ascendc::aclrtc::ACLRTC_SUCCESS); | ||
| 788 | + Json commandPrefixManifest = CreateManifest(); | ||
| 789 | + auto& arguments = commandPrefixManifest["kernels"][1]["objects"][0]["commands"][0]["cmd"]; | ||
| 790 | + Json commandPrefix = Json::array({arguments[0]}); | ||
| 791 | + for (const auto& argument : commandPrefixManifest["options"]["common_compile"]) { | ||
| 792 | + commandPrefix.push_back(argument); | ||
| 793 | + } | ||
| 794 | + commandPrefixManifest["options"]["command_prefix"] = std::move(commandPrefix); | ||
| 795 | + arguments.erase(0); | ||
| 796 | + arguments[0] = "${options:command_prefix}"; | ||
| 797 | + ASSERT_EQ( | ||
| 798 | + BuildPlanFromManifest( | ||
| 799 | + request, commandPrefixManifest, workspace.ResourcePath(), workspace.SourceDirectoryPath(), plan), | ||
| 800 | + ascendc::aclrtc::ACLRTC_SUCCESS); | ||
| 801 | + EXPECT_EQ(plan.compilationCommands[0].executablePath, expectedPlan.compilationCommands[0].executablePath); | ||
| 802 | + EXPECT_EQ(plan.compilationCommands[0].arguments, expectedPlan.compilationCommands[0].arguments); | ||
| 803 | + | ||
| 647 | Json relativeExecutableManifest = CreateManifest(); | 804 | Json relativeExecutableManifest = CreateManifest(); |
| 648 | relativeExecutableManifest["kernels"][1]["objects"][0]["commands"][0]["cmd"][0] = "bisheng"; | 805 | relativeExecutableManifest["kernels"][1]["objects"][0]["commands"][0]["cmd"][0] = "bisheng"; |
| 649 | EXPECT_EQ( | 806 | EXPECT_EQ( |
| 650 | - KernelCompilationPlanBuilder( | 807 | + BuildPlanFromManifest( |
| 651 | - request, relativeExecutableManifest, workspace.ResourcePath(), workspace.SourceDirectoryPath()) | 808 | + request, relativeExecutableManifest, workspace.ResourcePath(), workspace.SourceDirectoryPath(), plan), |
| 652 | - .BuildCompilationPlan(plan), | ||
| 653 | ascendc::aclrtc::ACLRTC_ERROR_FAILURE); | 809 | ascendc::aclrtc::ACLRTC_ERROR_FAILURE); |
| 654 | } | 810 | } |
| 655 | 811 | ||
| 656 | -TEST(KernelCompilationPlanBuilderTest, RequiresBasicAndRequestedSuperKernelObjects) | 812 | +TEST(KernelCompilationPlanBuilderTest, RequiresBasicAndFallsBackWhenSuperKernelIsAbsent) |
| 657 | { | 813 | { |
| 658 | KernelPlanTestWorkspace workspace; | 814 | KernelPlanTestWorkspace workspace; |
| 659 | ScopedEnvironmentVariable toolchainEnvironment("ACLRTC_TEST_TOOLCHAIN", workspace.ToolchainPath().string()); | 815 | ScopedEnvironmentVariable toolchainEnvironment("ACLRTC_TEST_TOOLCHAIN", workspace.ToolchainPath().string()); |
| @@ -668,19 +824,29 @@ TEST(KernelCompilationPlanBuilderTest, RequiresBasicAndRequestedSuperKernelObjec | |||
| 668 | Json manifestWithoutBasic = CreateManifest(); | 824 | Json manifestWithoutBasic = CreateManifest(); |
| 669 | manifestWithoutBasic["kernels"][1]["objects"].erase(0); | 825 | manifestWithoutBasic["kernels"][1]["objects"].erase(0); |
| 670 | EXPECT_EQ( | 826 | EXPECT_EQ( |
| 671 | - KernelCompilationPlanBuilder( | 827 | + BuildPlanFromManifest( |
| 672 | - request, manifestWithoutBasic, workspace.ResourcePath(), workspace.SourceDirectoryPath()) | 828 | + request, manifestWithoutBasic, workspace.ResourcePath(), workspace.SourceDirectoryPath(), plan), |
| 673 | - .BuildCompilationPlan(plan), | ||
| 674 | ascendc::aclrtc::ACLRTC_ERROR_FAILURE); | 829 | ascendc::aclrtc::ACLRTC_ERROR_FAILURE); |
| 675 | 830 | ||
| 676 | - request.compilationVariant = KernelCompilationVariant::BasicWithSuperKernel; | 831 | + request.enableSuperKernel = true; |
| 832 | + request.compilerOptions.superKernelOptions = {"--sk-only-test-option"}; | ||
| 677 | Json manifestWithoutSuperKernel = CreateManifest(); | 833 | Json manifestWithoutSuperKernel = CreateManifest(); |
| 678 | manifestWithoutSuperKernel["kernels"][1]["objects"].erase(1); | 834 | manifestWithoutSuperKernel["kernels"][1]["objects"].erase(1); |
| 679 | - EXPECT_EQ( | 835 | + ASSERT_EQ( |
| 680 | - KernelCompilationPlanBuilder( | 836 | + BuildPlanFromManifest( |
| 681 | - request, manifestWithoutSuperKernel, workspace.ResourcePath(), workspace.SourceDirectoryPath()) | 837 | + request, manifestWithoutSuperKernel, workspace.ResourcePath(), workspace.SourceDirectoryPath(), plan), |
| 682 | - .BuildCompilationPlan(plan), | 838 | + ascendc::aclrtc::ACLRTC_SUCCESS); |
| 683 | - ascendc::aclrtc::ACLRTC_ERROR_FAILURE); | 839 | + request.enableSuperKernel = false; |
| 840 | + KernelCompilationPlan basicPlan; | ||
| 841 | + ASSERT_EQ( | ||
| 842 | + BuildPlanFromManifest( | ||
| 843 | + request, manifestWithoutSuperKernel, workspace.ResourcePath(), workspace.SourceDirectoryPath(), basicPlan), | ||
| 844 | + ascendc::aclrtc::ACLRTC_SUCCESS); | ||
| 845 | + ASSERT_EQ(plan.compilationCommands.size(), basicPlan.compilationCommands.size()); | ||
| 846 | + for (size_t index = 0; index < plan.compilationCommands.size(); ++index) { | ||
| 847 | + EXPECT_EQ(plan.compilationCommands[index].executablePath, basicPlan.compilationCommands[index].executablePath); | ||
| 848 | + EXPECT_EQ(plan.compilationCommands[index].arguments, basicPlan.compilationCommands[index].arguments); | ||
| 849 | + } | ||
| 684 | } | 850 | } |
| 685 | 851 | ||
| 686 | TEST(KernelCompilationPlanBuilderTest, RejectsUnresolvableLinkInputs) | 852 | TEST(KernelCompilationPlanBuilderTest, RejectsUnresolvableLinkInputs) |
| @@ -699,25 +865,22 @@ TEST(KernelCompilationPlanBuilderTest, RejectsUnresolvableLinkInputs) | |||
| 699 | Json unresolvedLinkOptionManifest = CreateManifest(); | 865 | Json unresolvedLinkOptionManifest = CreateManifest(); |
| 700 | unresolvedLinkOptionManifest["kernels"][1]["link_options"] = Json::array({"${env:ACLRTC_TEST_MISSING_LINK_INPUT}"}); | 866 | unresolvedLinkOptionManifest["kernels"][1]["link_options"] = Json::array({"${env:ACLRTC_TEST_MISSING_LINK_INPUT}"}); |
| 701 | EXPECT_EQ( | 867 | EXPECT_EQ( |
| 702 | - KernelCompilationPlanBuilder( | 868 | + BuildPlanFromManifest( |
| 703 | - request, unresolvedLinkOptionManifest, workspace.ResourcePath(), workspace.SourceDirectoryPath()) | 869 | + request, unresolvedLinkOptionManifest, workspace.ResourcePath(), workspace.SourceDirectoryPath(), plan), |
| 704 | - .BuildCompilationPlan(plan), | ||
| 705 | ascendc::aclrtc::ACLRTC_ERROR_FAILURE); | 870 | ascendc::aclrtc::ACLRTC_ERROR_FAILURE); |
| 706 | 871 | ||
| 707 | Json unresolvedObjectOutputManifest = CreateManifest(); | 872 | Json unresolvedObjectOutputManifest = CreateManifest(); |
| 708 | unresolvedObjectOutputManifest["kernels"][1]["objects"][0]["outputs"][0] = "${env:ACLRTC_TEST_MISSING_LINK_INPUT}"; | 873 | unresolvedObjectOutputManifest["kernels"][1]["objects"][0]["outputs"][0] = "${env:ACLRTC_TEST_MISSING_LINK_INPUT}"; |
| 709 | EXPECT_EQ( | 874 | EXPECT_EQ( |
| 710 | - KernelCompilationPlanBuilder( | 875 | + BuildPlanFromManifest( |
| 711 | - request, unresolvedObjectOutputManifest, workspace.ResourcePath(), workspace.SourceDirectoryPath()) | 876 | + request, unresolvedObjectOutputManifest, workspace.ResourcePath(), workspace.SourceDirectoryPath(), plan), |
| 712 | - .BuildCompilationPlan(plan), | ||
| 713 | ascendc::aclrtc::ACLRTC_ERROR_FAILURE); | 877 | ascendc::aclrtc::ACLRTC_ERROR_FAILURE); |
| 714 | 878 | ||
| 715 | ScopedEnvironmentVariable missingLinkerEnvironment( | 879 | ScopedEnvironmentVariable missingLinkerEnvironment( |
| 716 | "ASCEND_HOME_PATH", (workspace.ResourcePath() / "missing-toolchain").string()); | 880 | "ASCEND_HOME_PATH", (workspace.ResourcePath() / "missing-toolchain").string()); |
| 717 | EXPECT_EQ( | 881 | EXPECT_EQ( |
| 718 | - KernelCompilationPlanBuilder( | 882 | + BuildPlanFromManifest( |
| 719 | - request, CreateManifest(), workspace.ResourcePath(), workspace.SourceDirectoryPath()) | 883 | + request, CreateManifest(), workspace.ResourcePath(), workspace.SourceDirectoryPath(), plan), |
| 720 | - .BuildCompilationPlan(plan), | ||
| 721 | ascendc::aclrtc::ACLRTC_ERROR_FAILURE); | 884 | ascendc::aclrtc::ACLRTC_ERROR_FAILURE); |
| 722 | } | 885 | } |
| 723 | 886 | ||
| @@ -733,32 +896,28 @@ TEST(KernelCompilationPlanBuilderTest, RejectsInvalidManifestSelectionInputs) | |||
| 733 | KernelCompilationPlan plan; | 896 | KernelCompilationPlan plan; |
| 734 | 897 | ||
| 735 | EXPECT_EQ( | 898 | EXPECT_EQ( |
| 736 | - KernelCompilationPlanBuilder(request, CreateManifest(), "relative-worktree", workspace.SourceDirectoryPath()) | 899 | + BuildPlanFromManifest(request, CreateManifest(), "relative-worktree", workspace.SourceDirectoryPath(), plan), |
| 737 | - .BuildCompilationPlan(plan), | ||
| 738 | ascendc::aclrtc::ACLRTC_ERROR_FAILURE); | 900 | ascendc::aclrtc::ACLRTC_ERROR_FAILURE); |
| 739 | 901 | ||
| 740 | Json unsupportedSchemaManifest = CreateManifest(); | 902 | Json unsupportedSchemaManifest = CreateManifest(); |
| 741 | unsupportedSchemaManifest["schema_version"] = "2.0"; | 903 | unsupportedSchemaManifest["schema_version"] = "2.0"; |
| 742 | EXPECT_EQ( | 904 | EXPECT_EQ( |
| 743 | - KernelCompilationPlanBuilder( | 905 | + BuildPlanFromManifest( |
| 744 | - request, unsupportedSchemaManifest, workspace.ResourcePath(), workspace.SourceDirectoryPath()) | 906 | + request, unsupportedSchemaManifest, workspace.ResourcePath(), workspace.SourceDirectoryPath(), plan), |
| 745 | - .BuildCompilationPlan(plan), | ||
| 746 | ascendc::aclrtc::ACLRTC_ERROR_FAILURE); | 907 | ascendc::aclrtc::ACLRTC_ERROR_FAILURE); |
| 747 | 908 | ||
| 748 | request.kernelName = "missing_kernel"; | 909 | request.kernelName = "missing_kernel"; |
| 749 | EXPECT_EQ( | 910 | EXPECT_EQ( |
| 750 | - KernelCompilationPlanBuilder( | 911 | + BuildPlanFromManifest( |
| 751 | - request, CreateManifest(), workspace.ResourcePath(), workspace.SourceDirectoryPath()) | 912 | + request, CreateManifest(), workspace.ResourcePath(), workspace.SourceDirectoryPath(), plan), |
| 752 | - .BuildCompilationPlan(plan), | ||
| 753 | ascendc::aclrtc::ACLRTC_ERROR_FAILURE); | 913 | ascendc::aclrtc::ACLRTC_ERROR_FAILURE); |
| 754 | 914 | ||
| 755 | request.kernelName = "add_custom_100000"; | 915 | request.kernelName = "add_custom_100000"; |
| 756 | Json malformedSchemaManifest = CreateManifest(); | 916 | Json malformedSchemaManifest = CreateManifest(); |
| 757 | malformedSchemaManifest["schema_version"] = Json::array(); | 917 | malformedSchemaManifest["schema_version"] = Json::array(); |
| 758 | EXPECT_EQ( | 918 | EXPECT_EQ( |
| 759 | - KernelCompilationPlanBuilder( | 919 | + BuildPlanFromManifest( |
| 760 | - request, malformedSchemaManifest, workspace.ResourcePath(), workspace.SourceDirectoryPath()) | 920 | + request, malformedSchemaManifest, workspace.ResourcePath(), workspace.SourceDirectoryPath(), plan), |
| 761 | - .BuildCompilationPlan(plan), | ||
| 762 | ascendc::aclrtc::ACLRTC_ERROR_FAILURE); | 921 | ascendc::aclrtc::ACLRTC_ERROR_FAILURE); |
| 763 | } | 922 | } |
| 764 | 923 | ||
| @@ -779,22 +938,19 @@ TEST(KernelCompilationPlanBuilderTest, RejectsMissingEnvironmentVariablesAtEachE | |||
| 779 | manifest["options"]["common_compile"] = Json::array({"${env:ACLRTC_TEST_MISSING_ENV}/include"}); | 938 | manifest["options"]["common_compile"] = Json::array({"${env:ACLRTC_TEST_MISSING_ENV}/include"}); |
| 780 | KernelCompilationPlan plan; | 939 | KernelCompilationPlan plan; |
| 781 | EXPECT_NE( | 940 | EXPECT_NE( |
| 782 | - KernelCompilationPlanBuilder(request, manifest, workspace.ResourcePath(), workspace.SourceDirectoryPath()) | 941 | + BuildPlanFromManifest(request, manifest, workspace.ResourcePath(), workspace.SourceDirectoryPath(), plan), |
| 783 | - .BuildCompilationPlan(plan), | ||
| 784 | ascendc::aclrtc::ACLRTC_SUCCESS); | 942 | ascendc::aclrtc::ACLRTC_SUCCESS); |
| 785 | 943 | ||
| 786 | manifest = CreateManifest(); | 944 | manifest = CreateManifest(); |
| 787 | manifest["kernels"][1]["constant_infos"][0]["file"] = "${env:ACLRTC_TEST_MISSING_ENV}/constants.h"; | 945 | manifest["kernels"][1]["constant_infos"][0]["file"] = "${env:ACLRTC_TEST_MISSING_ENV}/constants.h"; |
| 788 | EXPECT_NE( | 946 | EXPECT_NE( |
| 789 | - KernelCompilationPlanBuilder(request, manifest, workspace.ResourcePath(), workspace.SourceDirectoryPath()) | 947 | + BuildPlanFromManifest(request, manifest, workspace.ResourcePath(), workspace.SourceDirectoryPath(), plan), |
| 790 | - .BuildCompilationPlan(plan), | ||
| 791 | ascendc::aclrtc::ACLRTC_SUCCESS); | 948 | ascendc::aclrtc::ACLRTC_SUCCESS); |
| 792 | 949 | ||
| 793 | ASSERT_EQ(unsetenv("ASCEND_HOME_PATH"), 0); | 950 | ASSERT_EQ(unsetenv("ASCEND_HOME_PATH"), 0); |
| 794 | manifest = CreateManifest(); | 951 | manifest = CreateManifest(); |
| 795 | EXPECT_NE( | 952 | EXPECT_NE( |
| 796 | - KernelCompilationPlanBuilder(request, manifest, workspace.ResourcePath(), workspace.SourceDirectoryPath()) | 953 | + BuildPlanFromManifest(request, manifest, workspace.ResourcePath(), workspace.SourceDirectoryPath(), plan), |
| 797 | - .BuildCompilationPlan(plan), | ||
| 798 | ascendc::aclrtc::ACLRTC_SUCCESS); | 954 | ascendc::aclrtc::ACLRTC_SUCCESS); |
| 799 | } | 955 | } |
| 800 | 956 | ||
| @@ -813,8 +969,7 @@ TEST(KernelCompilationPlanBuilderTest, ReportsResourceWorktreeInspectionErrors) | |||
| 813 | 969 | ||
| 814 | KernelCompilationPlan plan; | 970 | KernelCompilationPlan plan; |
| 815 | EXPECT_NE( | 971 | EXPECT_NE( |
| 816 | - KernelCompilationPlanBuilder(request, CreateManifest(), selfReferentialLink, workspace.SourceDirectoryPath()) | 972 | + BuildPlanFromManifest(request, CreateManifest(), selfReferentialLink, workspace.SourceDirectoryPath(), plan), |
| 817 | - .BuildCompilationPlan(plan), | ||
| 818 | ascendc::aclrtc::ACLRTC_SUCCESS); | 973 | ascendc::aclrtc::ACLRTC_SUCCESS); |
| 819 | } | 974 | } |
| 820 | } // namespace | 975 | } // namespace |
| @@ -70,7 +70,7 @@ TEST(KernelSpecializationRequestTest, NormalizesBasicRequestAndCopiesOptions) | |||
| 70 | EXPECT_EQ(normalizedRequest.resourceId, RESOURCE_ID); | 70 | EXPECT_EQ(normalizedRequest.resourceId, RESOURCE_ID); |
| 71 | EXPECT_EQ(normalizedRequest.kernelName, "add_custom_100000"); | 71 | EXPECT_EQ(normalizedRequest.kernelName, "add_custom_100000"); |
| 72 | EXPECT_EQ(normalizedRequest.outputElfPath, "/tmp/kernel.elf"); | 72 | EXPECT_EQ(normalizedRequest.outputElfPath, "/tmp/kernel.elf"); |
| 73 | - EXPECT_EQ(normalizedRequest.compilationVariant, ascendc::aclrtc::KernelCompilationVariant::Basic); | 73 | + EXPECT_EQ(normalizedRequest.enableSuperKernel, false); |
| 74 | EXPECT_EQ(normalizedRequest.compilerOptions.basicOptions, (std::vector<std::string>{"-g", "-DVALUE=1"})); | 74 | EXPECT_EQ(normalizedRequest.compilerOptions.basicOptions, (std::vector<std::string>{"-g", "-DVALUE=1"})); |
| 75 | EXPECT_TRUE(normalizedRequest.compilerOptions.superKernelOptions.empty()); | 75 | EXPECT_TRUE(normalizedRequest.compilerOptions.superKernelOptions.empty()); |
| 76 | } | 76 | } |
| @@ -96,7 +96,7 @@ TEST(KernelSpecializationRequestTest, EnablesSuperKernelAndRemovesControlOption) | |||
| 96 | 96 | ||
| 97 | ascendc::aclrtc::NormalizedKernelSpecializationRequest normalizedRequest; | 97 | ascendc::aclrtc::NormalizedKernelSpecializationRequest normalizedRequest; |
| 98 | EXPECT_EQ(ascendc::aclrtc::NormalizeKernelSpecializationRequest(request, "/tmp/kernel.elf", normalizedRequest), 0); | 98 | EXPECT_EQ(ascendc::aclrtc::NormalizeKernelSpecializationRequest(request, "/tmp/kernel.elf", normalizedRequest), 0); |
| 99 | - EXPECT_EQ(normalizedRequest.compilationVariant, ascendc::aclrtc::KernelCompilationVariant::BasicWithSuperKernel); | 99 | + EXPECT_EQ(normalizedRequest.enableSuperKernel, true); |
| 100 | EXPECT_EQ(normalizedRequest.compilerOptions.superKernelOptions, (std::vector<std::string>{"-g", "-DDCCI_OFF"})); | 100 | EXPECT_EQ(normalizedRequest.compilerOptions.superKernelOptions, (std::vector<std::string>{"-g", "-DDCCI_OFF"})); |
| 101 | } | 101 | } |
| 102 | 102 | ||
| @@ -109,7 +109,7 @@ TEST(KernelSpecializationRequestTest, IgnoresSuperKernelOptionsWithoutEnable) | |||
| 109 | 109 | ||
| 110 | ascendc::aclrtc::NormalizedKernelSpecializationRequest normalizedRequest; | 110 | ascendc::aclrtc::NormalizedKernelSpecializationRequest normalizedRequest; |
| 111 | EXPECT_EQ(ascendc::aclrtc::NormalizeKernelSpecializationRequest(request, "/tmp/kernel.elf", normalizedRequest), 0); | 111 | EXPECT_EQ(ascendc::aclrtc::NormalizeKernelSpecializationRequest(request, "/tmp/kernel.elf", normalizedRequest), 0); |
| 112 | - EXPECT_EQ(normalizedRequest.compilationVariant, ascendc::aclrtc::KernelCompilationVariant::Basic); | 112 | + EXPECT_EQ(normalizedRequest.enableSuperKernel, false); |
| 113 | EXPECT_TRUE(normalizedRequest.compilerOptions.superKernelOptions.empty()); | 113 | EXPECT_TRUE(normalizedRequest.compilerOptions.superKernelOptions.empty()); |
| 114 | } | 114 | } |
| 115 | 115 | ||
| @@ -161,7 +161,9 @@ private: | |||
| 161 | {"kernels", Json::array( | 161 | {"kernels", Json::array( |
| 162 | {{{"kernel_name", "add_custom_100000"}, | 162 | {{{"kernel_name", "add_custom_100000"}, |
| 163 | {"constant_infos", Json::array( | 163 | {"constant_infos", Json::array( |
| 164 | - {{{"parameter_index", 0}, | 164 | + {{{"name", "tiling"}, |
| 165 | + {"parameter_index", 0}, | ||
| 166 | + {"arg_type", "pointer"}, | ||
| 165 | {"byte_size", 2}, | 167 | {"byte_size", 2}, |
| 166 | {"file", "${resource}/resources/include/constants.h"}, | 168 | {"file", "${resource}/resources/include/constants.h"}, |
| 167 | {"template", "@@STATIC_TILING@@"}}})}, | 169 | {"template", "@@STATIC_TILING@@"}}})}, |
| @@ -207,6 +207,7 @@ add_executable(ascendc_ut_asc_compile_exporter | |||
| 207 | asc_compile_exporter/test_file_utils.cpp | 207 | asc_compile_exporter/test_file_utils.cpp |
| 208 | asc_compile_exporter/test_manifest_bundle_types.cpp | 208 | asc_compile_exporter/test_manifest_bundle_types.cpp |
| 209 | common/test_process_executor.cpp | 209 | common/test_process_executor.cpp |
| 210 | + common/test_manifest_constant.cpp | ||
| 210 | asc_compile_exporter/test_resource_manifest_validator.cpp | 211 | asc_compile_exporter/test_resource_manifest_validator.cpp |
| 211 | common/test_directory_cleanup_guard.cpp | 212 | common/test_directory_cleanup_guard.cpp |
| 212 | asc_compile_exporter/test_ascendc_tool_log.cpp | 213 | asc_compile_exporter/test_ascendc_tool_log.cpp |
| @@ -214,6 +215,7 @@ add_executable(ascendc_ut_asc_compile_exporter | |||
| 214 | ${ASCENDC_DIR}/tools/build/asc_compile_exporter/collected_manifest_repository.cpp | 215 | ${ASCENDC_DIR}/tools/build/asc_compile_exporter/collected_manifest_repository.cpp |
| 215 | ${ASCENDC_DIR}/tools/build/asc_compile_exporter/manifest_bundle_compiler.cpp | 216 | ${ASCENDC_DIR}/tools/build/asc_compile_exporter/manifest_bundle_compiler.cpp |
| 216 | ${ASCENDC_DIR}/tools/build/asc_compile_exporter/resource_manifest_validator.cpp | 217 | ${ASCENDC_DIR}/tools/build/asc_compile_exporter/resource_manifest_validator.cpp |
| 218 | + ${ASCENDC_DIR}/tools/build/common/manifest_constant.cpp | ||
| 217 | ${ASCENDC_DIR}/tools/build/common/file_utils.cpp | 219 | ${ASCENDC_DIR}/tools/build/common/file_utils.cpp |
| 218 | ${ASCENDC_DIR}/tools/build/common/process_executor.cpp | 220 | ${ASCENDC_DIR}/tools/build/common/process_executor.cpp |
| 219 | ${ASCENDC_DIR}/tools/build/common/directory_cleanup_guard.cpp | 221 | ${ASCENDC_DIR}/tools/build/common/directory_cleanup_guard.cpp |
| @@ -33,6 +33,7 @@ Json MakeValidManifest() | |||
| 33 | { | 33 | { |
| 34 | Json constant = { | 34 | Json constant = { |
| 35 | {"name", "weight"}, | 35 | {"name", "weight"}, |
| 36 | + {"arg_type", "pointer"}, | ||
| 36 | {"parameter_index", Json::number_unsigned_t(0U)}, | 37 | {"parameter_index", Json::number_unsigned_t(0U)}, |
| 37 | {"byte_size", Json::number_unsigned_t(4U)}, | 38 | {"byte_size", Json::number_unsigned_t(4U)}, |
| 38 | {"file", "${resource}/resources/weight.bin"}, | 39 | {"file", "${resource}/resources/weight.bin"}, |
| @@ -133,6 +134,20 @@ TEST_F(ResourceManifestValidatorTest, AcceptsCompleteAndMinimalValidManifests) | |||
| 133 | Command(namedOptions)["cmd"][0U] = "${options:custom_compile}"; | 134 | Command(namedOptions)["cmd"][0U] = "${options:custom_compile}"; |
| 134 | Command(namedOptions)["cmd"].insert(Command(namedOptions)["cmd"].begin() + 1U, "${options:custom_compile}"); | 135 | Command(namedOptions)["cmd"].insert(Command(namedOptions)["cmd"].begin() + 1U, "${options:custom_compile}"); |
| 135 | EXPECT_TRUE(Validate(namedOptions)); | 136 | EXPECT_TRUE(Validate(namedOptions)); |
| 137 | + | ||
| 138 | + Json pointerConstant = MakeValidManifest(); | ||
| 139 | + Constant(pointerConstant)["arg_type"] = "pointer"; | ||
| 140 | + EXPECT_TRUE(Validate(pointerConstant)); | ||
| 141 | + | ||
| 142 | + Json explicitStructConstant = MakeValidManifest(); | ||
| 143 | + Constant(explicitStructConstant)["arg_type"] = "struct"; | ||
| 144 | + Constant(explicitStructConstant).erase("byte_size"); | ||
| 145 | + EXPECT_TRUE(Validate(explicitStructConstant)); | ||
| 146 | + | ||
| 147 | + Json defaultStructConstant = MakeValidManifest(); | ||
| 148 | + Constant(defaultStructConstant).erase("arg_type"); | ||
| 149 | + Constant(defaultStructConstant).erase("byte_size"); | ||
| 150 | + EXPECT_TRUE(Validate(defaultStructConstant)); | ||
| 136 | } | 151 | } |
| 137 | 152 | ||
| 138 | TEST_F(ResourceManifestValidatorTest, RejectsInvalidTopLevelFields) | 153 | TEST_F(ResourceManifestValidatorTest, RejectsInvalidTopLevelFields) |
| @@ -224,21 +239,7 @@ TEST_F(ResourceManifestValidatorTest, ValidatesMarkersAndReferencedPaths) | |||
| 224 | TEST_F(ResourceManifestValidatorTest, ValidatesConstants) | 239 | TEST_F(ResourceManifestValidatorTest, ValidatesConstants) |
| 225 | { | 240 | { |
| 226 | ExpectInvalid( | 241 | ExpectInvalid( |
| 227 | - "constant is not an object", [](Json& manifest) { Kernel(manifest)["constant_infos"][0U] = "weight"; }); | 242 | + "struct must not contain byte_size", [](Json& manifest) { Constant(manifest)["arg_type"] = "struct"; }); |
| 228 | - ExpectInvalid("constant has extra field", [](Json& manifest) { Constant(manifest)["extra"] = true; }); | ||
| 229 | - ExpectInvalid("constant name is missing", [](Json& manifest) { | ||
| 230 | - Constant(manifest).erase("name"); | ||
| 231 | - Constant(manifest)["extra"] = true; | ||
| 232 | - }); | ||
| 233 | - ExpectInvalid("constant name has wrong type", [](Json& manifest) { Constant(manifest)["name"] = 1U; }); | ||
| 234 | - ExpectInvalid("constant name is empty", [](Json& manifest) { Constant(manifest)["name"] = ""; }); | ||
| 235 | - ExpectInvalid("parameter_index has wrong type", [](Json& manifest) { Constant(manifest)["parameter_index"] = -1; }); | ||
| 236 | - ExpectInvalid("byte_size has wrong type", [](Json& manifest) { Constant(manifest)["byte_size"] = "4"; }); | ||
| 237 | - ExpectInvalid( | ||
| 238 | - "byte_size is zero", [](Json& manifest) { Constant(manifest)["byte_size"] = Json::number_unsigned_t(0U); }); | ||
| 239 | - ExpectInvalid("constant file has wrong type", [](Json& manifest) { Constant(manifest)["file"] = 1U; }); | ||
| 240 | - ExpectInvalid("constant template has wrong type", [](Json& manifest) { Constant(manifest)["template"] = 1U; }); | ||
| 241 | - ExpectInvalid("constant template is empty", [](Json& manifest) { Constant(manifest)["template"] = ""; }); | ||
| 242 | ExpectInvalid( | 243 | ExpectInvalid( |
| 243 | "constant file lacks resource prefix", [](Json& manifest) { Constant(manifest)["file"] = "resources/x"; }); | 244 | "constant file lacks resource prefix", [](Json& manifest) { Constant(manifest)["file"] = "resources/x"; }); |
| 244 | ExpectInvalid("constant file is outside resource_path", [](Json& manifest) { | 245 | ExpectInvalid("constant file is outside resource_path", [](Json& manifest) { |
| @@ -0,0 +1,163 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2026 Huawei Technologies Co., Ltd. | ||
| 3 | + * This program is free software, you can redistribute it and/or modify it under the terms and conditions of | ||
| 4 | + * CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 5 | + * Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 6 | + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, | ||
| 7 | + * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | + * See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | + */ | ||
| 10 | + | ||
| 11 | + | ||
| 12 | + | ||
| 13 | + | ||
| 14 | + | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | +namespace { | ||
| 19 | +using Json = nlohmann::json; | ||
| 20 | +using ascendc::ManifestConstant; | ||
| 21 | + | ||
| 22 | +Json MakeConstant() | ||
| 23 | +{ | ||
| 24 | + return {{"name", "tiling"}, {"parameter_index", 2}, {"file", "${resource}/tiling.h"}, {"template", "@@TILING@@"}}; | ||
| 25 | +} | ||
| 26 | + | ||
| 27 | +TEST(ManifestConstantTest, ResolvesDefaultAndExplicitStructSizes) | ||
| 28 | +{ | ||
| 29 | + for (bool explicitType : {false, true}) { | ||
| 30 | + Json input = MakeConstant(); | ||
| 31 | + if (explicitType) { | ||
| 32 | + input["arg_type"] = "struct"; | ||
| 33 | + } | ||
| 34 | + ManifestConstant constant; | ||
| 35 | + ASSERT_TRUE(constant.ParseDefinition(input)); | ||
| 36 | + input.clear(); | ||
| 37 | + EXPECT_EQ(constant.GetName(), "tiling"); | ||
| 38 | + EXPECT_EQ(constant.GetParameterIndex(), 2U); | ||
| 39 | + EXPECT_EQ(constant.GetTargetFile(), "${resource}/tiling.h"); | ||
| 40 | + EXPECT_EQ(constant.GetTemplateText(), "@@TILING@@"); | ||
| 41 | + uint8_t byte = 0; | ||
| 42 | + const void* addresses[] = {nullptr, nullptr, &byte}; | ||
| 43 | + const uint64_t sizes[] = {0U, 0U, 17U}; | ||
| 44 | + ASSERT_TRUE(constant.BindArgument(3U, addresses, sizes)); | ||
| 45 | + EXPECT_EQ(constant.GetBoundData(), &byte); | ||
| 46 | + EXPECT_EQ(constant.GetBoundByteSize(), 17U); | ||
| 47 | + } | ||
| 48 | +} | ||
| 49 | + | ||
| 50 | +TEST(ManifestConstantTest, PreservesSignedAndUnsignedPointerSizeBoundaries) | ||
| 51 | +{ | ||
| 52 | + for (const Json& size : std::vector<Json>{1, int64_t{4}, std::numeric_limits<uint64_t>::max()}) { | ||
| 53 | + Json input = MakeConstant(); | ||
| 54 | + input["arg_type"] = "pointer"; | ||
| 55 | + input["byte_size"] = size; | ||
| 56 | + input["parameter_index"] = std::numeric_limits<uint64_t>::max(); | ||
| 57 | + ManifestConstant constant; | ||
| 58 | + ASSERT_TRUE(constant.ParseDefinition(input)); | ||
| 59 | + EXPECT_EQ(constant.GetParameterIndex(), std::numeric_limits<uint64_t>::max()); | ||
| 60 | + input["parameter_index"] = 0; | ||
| 61 | + ASSERT_TRUE(constant.ParseDefinition(input)); | ||
| 62 | + uint8_t byte = 0; | ||
| 63 | + const void* addresses[] = {&byte}; | ||
| 64 | + ASSERT_TRUE(constant.BindArgument(1U, addresses, nullptr)); | ||
| 65 | + EXPECT_EQ(constant.GetBoundByteSize(), size.get<uint64_t>()); | ||
| 66 | + } | ||
| 67 | +} | ||
| 68 | + | ||
| 69 | +TEST(ManifestConstantTest, RejectsInvalidFieldsWithoutChangingParsedConstant) | ||
| 70 | +{ | ||
| 71 | + std::vector<Json> inputs{nullptr, Json::array(), 1}; | ||
| 72 | + for (const char* field : {"name", "parameter_index", "file", "template"}) { | ||
| 73 | + Json input = MakeConstant(); | ||
| 74 | + input.erase(field); | ||
| 75 | + inputs.push_back(input); | ||
| 76 | + } | ||
| 77 | + for (const Json& fields : std::vector<Json>{ | ||
| 78 | + {{"name", ""}}, | ||
| 79 | + {{"name", 1}}, | ||
| 80 | + {{"file", ""}}, | ||
| 81 | + {{"file", nullptr}}, | ||
| 82 | + {{"template", ""}}, | ||
| 83 | + {{"template", true}}, | ||
| 84 | + {{"parameter_index", -1}}, | ||
| 85 | + {{"parameter_index", 1.5}}, | ||
| 86 | + {{"parameter_index", "2"}}, | ||
| 87 | + {{"parameter_index", true}}, | ||
| 88 | + {{"arg_type", nullptr}}, | ||
| 89 | + {{"arg_type", "other"}}, | ||
| 90 | + {{"extra", 1}}, | ||
| 91 | + {{"byte_size", 4}}, | ||
| 92 | + {{"arg_type", "struct"}, {"byte_size", 4}}, | ||
| 93 | + {{"arg_type", "pointer"}}, | ||
| 94 | + {{"arg_type", "pointer"}, {"byte_size", 0}}, | ||
| 95 | + {{"arg_type", "pointer"}, {"byte_size", -1}}, | ||
| 96 | + {{"arg_type", "pointer"}, {"byte_size", 1.5}}, | ||
| 97 | + {{"arg_type", "pointer"}, {"byte_size", "4"}}, | ||
| 98 | + {{"arg_type", "pointer"}, {"byte_size", true}}}) { | ||
| 99 | + Json input = MakeConstant(); | ||
| 100 | + input.update(fields); | ||
| 101 | + inputs.push_back(input); | ||
| 102 | + } | ||
| 103 | + ManifestConstant constant; | ||
| 104 | + Json valid = MakeConstant(); | ||
| 105 | + valid.update({{"arg_type", "pointer"}, {"byte_size", 7}}); | ||
| 106 | + ASSERT_TRUE(constant.ParseDefinition(valid)); | ||
| 107 | + uint8_t byte = 0; | ||
| 108 | + const void* addresses[] = {nullptr, nullptr, &byte}; | ||
| 109 | + ASSERT_TRUE(constant.BindArgument(3U, addresses, nullptr)); | ||
| 110 | + for (const Json& input : inputs) { | ||
| 111 | + SCOPED_TRACE(input.dump()); | ||
| 112 | + EXPECT_FALSE(constant.ParseDefinition(input)); | ||
| 113 | + EXPECT_EQ(constant.GetName(), "tiling"); | ||
| 114 | + EXPECT_EQ(constant.GetParameterIndex(), 2U); | ||
| 115 | + EXPECT_EQ(constant.GetTargetFile(), "${resource}/tiling.h"); | ||
| 116 | + EXPECT_EQ(constant.GetTemplateText(), "@@TILING@@"); | ||
| 117 | + EXPECT_EQ(constant.GetBoundData(), &byte); | ||
| 118 | + EXPECT_EQ(constant.GetBoundByteSize(), 7U); | ||
| 119 | + } | ||
| 120 | +} | ||
| 121 | +TEST(ManifestConstantTest, RejectsBindingBeforeParsingAndResetsBindingAfterSuccessfulParse) | ||
| 122 | +{ | ||
| 123 | + ManifestConstant constant; | ||
| 124 | + uint8_t first = 1; | ||
| 125 | + uint8_t second = 2; | ||
| 126 | + const void* addresses[] = {nullptr, nullptr, &first}; | ||
| 127 | + uint64_t sizes[] = {0U, 0U, 1U}; | ||
| 128 | + EXPECT_FALSE(constant.BindArgument(3U, addresses, sizes)); | ||
| 129 | + EXPECT_EQ(constant.GetBoundData(), nullptr); | ||
| 130 | + EXPECT_EQ(constant.GetBoundByteSize(), 0U); | ||
| 131 | + EXPECT_FALSE(constant.ParseDefinition(Json::object())); | ||
| 132 | + ASSERT_TRUE(constant.ParseDefinition(MakeConstant())); | ||
| 133 | + ASSERT_TRUE(constant.BindArgument(3U, addresses, sizes)); | ||
| 134 | + addresses[2] = &second; | ||
| 135 | + sizes[2] = 2U; | ||
| 136 | + ASSERT_TRUE(constant.BindArgument(3U, addresses, sizes)); | ||
| 137 | + EXPECT_EQ(constant.GetBoundData(), &second); | ||
| 138 | + EXPECT_EQ(constant.GetBoundByteSize(), 2U); | ||
| 139 | + ASSERT_TRUE(constant.ParseDefinition(MakeConstant())); | ||
| 140 | + EXPECT_EQ(constant.GetBoundData(), nullptr); | ||
| 141 | + EXPECT_EQ(constant.GetBoundByteSize(), 0U); | ||
| 142 | + ASSERT_TRUE(constant.BindArgument(3U, addresses, sizes)); | ||
| 143 | +} | ||
| 144 | + | ||
| 145 | +TEST(ManifestConstantTest, RejectsInvalidArgumentsWithoutChangingBinding) | ||
| 146 | +{ | ||
| 147 | + ManifestConstant constant; | ||
| 148 | + ASSERT_TRUE(constant.ParseDefinition(MakeConstant())); | ||
| 149 | + uint8_t byte = 0; | ||
| 150 | + const void* addresses[] = {nullptr, nullptr, &byte}; | ||
| 151 | + const void* nullAddresses[] = {nullptr, nullptr, nullptr}; | ||
| 152 | + const uint64_t sizes[] = {0U, 0U, 1U}; | ||
| 153 | + const uint64_t zeroSizes[] = {0U, 0U, 0U}; | ||
| 154 | + ASSERT_TRUE(constant.BindArgument(3U, addresses, sizes)); | ||
| 155 | + EXPECT_FALSE(constant.BindArgument(3U, nullptr, sizes)); | ||
| 156 | + EXPECT_FALSE(constant.BindArgument(2U, addresses, sizes)); | ||
| 157 | + EXPECT_FALSE(constant.BindArgument(3U, nullAddresses, sizes)); | ||
| 158 | + EXPECT_FALSE(constant.BindArgument(3U, addresses, nullptr)); | ||
| 159 | + EXPECT_FALSE(constant.BindArgument(3U, addresses, zeroSizes)); | ||
| 160 | + EXPECT_EQ(constant.GetBoundData(), &byte); | ||
| 161 | + EXPECT_EQ(constant.GetBoundByteSize(), 1U); | ||
| 162 | +} | ||
| 163 | +} // namespace | ||
| @@ -14,6 +14,7 @@ add_library(acl_rtc SHARED | |||
| 14 | ${SRC} | 14 | ${SRC} |
| 15 | ${SPECIALIZATION_SRC} | 15 | ${SPECIALIZATION_SRC} |
| 16 | ${CMAKE_CURRENT_SOURCE_DIR}/../build/common/file_utils.cpp | 16 | ${CMAKE_CURRENT_SOURCE_DIR}/../build/common/file_utils.cpp |
| 17 | + ${CMAKE_CURRENT_SOURCE_DIR}/../build/common/manifest_constant.cpp | ||
| 17 | ${CMAKE_CURRENT_SOURCE_DIR}/../build/common/process_executor.cpp | 18 | ${CMAKE_CURRENT_SOURCE_DIR}/../build/common/process_executor.cpp |
| 18 | ${CMAKE_CURRENT_SOURCE_DIR}/../build/common/directory_cleanup_guard.cpp | 19 | ${CMAKE_CURRENT_SOURCE_DIR}/../build/common/directory_cleanup_guard.cpp |
| 19 | ) | 20 | ) |
| @@ -0,0 +1,42 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2026 Huawei Technologies Co., Ltd. | ||
| 3 | + * This program is free software, you can redistribute it and/or modify it under the terms and conditions of | ||
| 4 | + * CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 5 | + * Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 6 | + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, | ||
| 7 | + * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | + * See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | + */ | ||
| 10 | + | ||
| 11 | + | ||
| 12 | + | ||
| 13 | + | ||
| 14 | + | ||
| 15 | + | ||
| 16 | + | ||
| 17 | +namespace ascendc { | ||
| 18 | +namespace aclrtc { | ||
| 19 | + | ||
| 20 | +enum class ManifestObjectKind { Basic, SuperKernel }; | ||
| 21 | + | ||
| 22 | +struct ManifestCommand { | ||
| 23 | + CompilationCommandKind commandKind{CompilationCommandKind::Compile}; | ||
| 24 | + ManifestObjectKind objectKind{ManifestObjectKind::Basic}; | ||
| 25 | + std::optional<uint32_t> parallelStage; | ||
| 26 | + std::string diagnosticLabel; | ||
| 27 | + std::string executable; | ||
| 28 | + std::vector<std::string> arguments; | ||
| 29 | +}; | ||
| 30 | + | ||
| 31 | +// Owns the selected fields independently of the source JSON. | ||
| 32 | +struct CompilationManifest { | ||
| 33 | + std::vector<ManifestConstant> constants; | ||
| 34 | + std::vector<ManifestCommand> commands; | ||
| 35 | + std::vector<std::string> linkOptions; | ||
| 36 | + std::vector<std::string> linkInputs; | ||
| 37 | +}; | ||
| 38 | + | ||
| 39 | +} // namespace aclrtc | ||
| 40 | +} // namespace ascendc | ||
| 41 | + | ||
| 42 | + | ||
| @@ -0,0 +1,217 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2026 Huawei Technologies Co., Ltd. | ||
| 3 | + * This program is free software, you can redistribute it and/or modify it under the terms and conditions of | ||
| 4 | + * CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 5 | + * Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 6 | + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, | ||
| 7 | + * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | + * See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | + */ | ||
| 10 | + | ||
| 11 | + | ||
| 12 | + | ||
| 13 | + | ||
| 14 | + | ||
| 15 | + | ||
| 16 | + | ||
| 17 | +namespace ascendc { | ||
| 18 | +namespace aclrtc { | ||
| 19 | +namespace { | ||
| 20 | +using Json = nlohmann::json; | ||
| 21 | +constexpr char SCHEMA_VERSION[] = "1.0"; | ||
| 22 | +constexpr char OPTIONS_PREFIX[] = "${options:"; | ||
| 23 | + | ||
| 24 | +bool ReadBoundedNonnegativeInteger(const Json& value, uint64_t maximum, uint64_t& result) | ||
| 25 | +{ | ||
| 26 | + if (!value.is_number_integer() || (!value.is_number_unsigned() && value.get<int64_t>() < 0)) { | ||
| 27 | + return false; | ||
| 28 | + } | ||
| 29 | + result = value.get<uint64_t>(); | ||
| 30 | + return result <= maximum; | ||
| 31 | +} | ||
| 32 | + | ||
| 33 | +} // namespace | ||
| 34 | + | ||
| 35 | +aclError CompilationManifestParser::ParseConstants(const Json& kernel, std::vector<ManifestConstant>& constants) const | ||
| 36 | +{ | ||
| 37 | + const auto infos = kernel.find("constant_infos"); | ||
| 38 | + if (infos == kernel.end() || !infos->is_array() || infos->empty()) { | ||
| 39 | + ASCENDLOGE("Selected kernel requires a nonempty constant_infos array"); | ||
| 40 | + return ACLRTC_ERROR_FAILURE; | ||
| 41 | + } | ||
| 42 | + for (size_t index = 0; index < infos->size(); ++index) { | ||
| 43 | + const Json& info = infos->at(index); | ||
| 44 | + ManifestConstant spec; | ||
| 45 | + if (!spec.ParseDefinition(info)) { | ||
| 46 | + return ACLRTC_ERROR_FAILURE; | ||
| 47 | + } | ||
| 48 | + constants.emplace_back(std::move(spec)); | ||
| 49 | + } | ||
| 50 | + return ACLRTC_SUCCESS; | ||
| 51 | +} | ||
| 52 | + | ||
| 53 | +aclError CompilationManifestParser::ExpandOptionsReference( | ||
| 54 | + const std::string& argument, const std::string& location, std::vector<std::string>& arguments) const | ||
| 55 | +{ | ||
| 56 | + if (argument.compare(0, sizeof(OPTIONS_PREFIX) - 1U, OPTIONS_PREFIX) != 0 || | ||
| 57 | + argument.size() <= sizeof(OPTIONS_PREFIX) || argument.back() != '}') { | ||
| 58 | + arguments.push_back(argument); | ||
| 59 | + return ACLRTC_SUCCESS; | ||
| 60 | + } | ||
| 61 | + const std::string name = argument.substr(sizeof(OPTIONS_PREFIX) - 1U, argument.size() - sizeof(OPTIONS_PREFIX)); | ||
| 62 | + const auto options = borrowedManifest_.find("options"); | ||
| 63 | + if (options == borrowedManifest_.end() || !options->is_object() || !options->contains(name)) { | ||
| 64 | + ASCENDLOGE("Manifest value %s references undefined options key '%s'", location.c_str(), name.c_str()); | ||
| 65 | + return ACLRTC_ERROR_FAILURE; | ||
| 66 | + } | ||
| 67 | + const auto values = options->at(name).get<std::vector<std::string>>(); | ||
| 68 | + arguments.insert(arguments.end(), values.begin(), values.end()); | ||
| 69 | + return ACLRTC_SUCCESS; | ||
| 70 | +} | ||
| 71 | + | ||
| 72 | +aclError CompilationManifestParser::ParseCommand( | ||
| 73 | + const Json& command, const std::string& objectName, ManifestObjectKind objectKind, size_t index, | ||
| 74 | + ManifestCommand& spec) const | ||
| 75 | +{ | ||
| 76 | + const std::string type = command.at("type").get<std::string>(); | ||
| 77 | + if (type == "compile") { | ||
| 78 | + spec.commandKind = CompilationCommandKind::Compile; | ||
| 79 | + } else if (type == "objcopy") { | ||
| 80 | + spec.commandKind = CompilationCommandKind::ObjectCopy; | ||
| 81 | + } else { | ||
| 82 | + ASCENDLOGE( | ||
| 83 | + "Manifest object %s command[%zu] has unsupported type '%s'", objectName.c_str(), index, type.c_str()); | ||
| 84 | + return ACLRTC_ERROR_FAILURE; | ||
| 85 | + } | ||
| 86 | + spec.objectKind = objectKind; | ||
| 87 | + spec.diagnosticLabel = objectName + "/" + type + "[" + std::to_string(index) + "]"; | ||
| 88 | + if (command.contains("stage")) { | ||
| 89 | + uint64_t stage = 0U; | ||
| 90 | + if (!ReadBoundedNonnegativeInteger(command.at("stage"), std::numeric_limits<uint32_t>::max(), stage)) { | ||
| 91 | + ASCENDLOGE("Manifest command %s has invalid stage", spec.diagnosticLabel.c_str()); | ||
| 92 | + return ACLRTC_ERROR_FAILURE; | ||
| 93 | + } | ||
| 94 | + spec.parallelStage = static_cast<uint32_t>(stage); | ||
| 95 | + } | ||
| 96 | + const auto argv = command.at("cmd").get<std::vector<std::string>>(); | ||
| 97 | + if (argv.empty()) { | ||
| 98 | + ASCENDLOGE("Manifest command %s has an empty cmd array", spec.diagnosticLabel.c_str()); | ||
| 99 | + return ACLRTC_ERROR_FAILURE; | ||
| 100 | + } | ||
| 101 | + std::vector<std::string> expandedArguments; | ||
| 102 | + for (size_t argumentIndex = 0U; argumentIndex < argv.size(); ++argumentIndex) { | ||
| 103 | + const aclError result = ExpandOptionsReference( | ||
| 104 | + argv[argumentIndex], spec.diagnosticLabel + ".cmd[" + std::to_string(argumentIndex) + "]", | ||
| 105 | + expandedArguments); | ||
| 106 | + if (result != ACLRTC_SUCCESS) { | ||
| 107 | + return result; | ||
| 108 | + } | ||
| 109 | + } | ||
| 110 | + if (expandedArguments.empty()) { | ||
| 111 | + ASCENDLOGE("Manifest command %s expands to an empty cmd array", spec.diagnosticLabel.c_str()); | ||
| 112 | + return ACLRTC_ERROR_FAILURE; | ||
| 113 | + } | ||
| 114 | + spec.executable = std::move(expandedArguments.front()); | ||
| 115 | + expandedArguments.erase(expandedArguments.begin()); | ||
| 116 | + spec.arguments = std::move(expandedArguments); | ||
| 117 | + return ACLRTC_SUCCESS; | ||
| 118 | +} | ||
| 119 | + | ||
| 120 | +aclError CompilationManifestParser::ParseSelectedObjects( | ||
| 121 | + const Json& kernel, bool enableSuperKernel, CompilationManifest& spec) const | ||
| 122 | +{ | ||
| 123 | + bool foundBasic = false; | ||
| 124 | + bool foundSuperKernel = false; | ||
| 125 | + const auto& objects = kernel.at("objects"); | ||
| 126 | + if (!objects.is_array()) { | ||
| 127 | + ASCENDLOGE("Selected kernel objects must be an array"); | ||
| 128 | + return ACLRTC_ERROR_FAILURE; | ||
| 129 | + } | ||
| 130 | + for (const auto& object : objects) { | ||
| 131 | + const std::string type = object.at("object_type").get<std::string>(); | ||
| 132 | + ManifestObjectKind kind; | ||
| 133 | + if (type == "basic") { | ||
| 134 | + foundBasic = true; | ||
| 135 | + kind = ManifestObjectKind::Basic; | ||
| 136 | + } else if (type == "sk") { | ||
| 137 | + foundSuperKernel = true; | ||
| 138 | + if (!enableSuperKernel) { | ||
| 139 | + continue; | ||
| 140 | + } | ||
| 141 | + kind = ManifestObjectKind::SuperKernel; | ||
| 142 | + } else { | ||
| 143 | + continue; | ||
| 144 | + } | ||
| 145 | + const std::string name = object.at("object_name").get<std::string>(); | ||
| 146 | + const auto& commands = object.at("commands"); | ||
| 147 | + if (!commands.is_array() || commands.empty()) { | ||
| 148 | + ASCENDLOGE("Selected object %s requires a nonempty commands array", name.c_str()); | ||
| 149 | + return ACLRTC_ERROR_FAILURE; | ||
| 150 | + } | ||
| 151 | + for (size_t index = 0; index < commands.size(); ++index) { | ||
| 152 | + ManifestCommand command; | ||
| 153 | + const aclError result = ParseCommand(commands.at(index), name, kind, index, command); | ||
| 154 | + if (result != ACLRTC_SUCCESS) { | ||
| 155 | + return result; | ||
| 156 | + } | ||
| 157 | + spec.commands.emplace_back(std::move(command)); | ||
| 158 | + } | ||
| 159 | + const auto outputs = object.at("outputs").get<std::vector<std::string>>(); | ||
| 160 | + spec.linkInputs.insert(spec.linkInputs.end(), outputs.begin(), outputs.end()); | ||
| 161 | + } | ||
| 162 | + if (!foundBasic) { | ||
| 163 | + ASCENDLOGE("Selected kernel is missing a required basic object"); | ||
| 164 | + return ACLRTC_ERROR_FAILURE; | ||
| 165 | + } | ||
| 166 | + if (enableSuperKernel && !foundSuperKernel) { | ||
| 167 | + ASCENDLOGI("Selected kernel has no sk object; compiling basic only despite --enable-super-kernel"); | ||
| 168 | + } | ||
| 169 | + return ACLRTC_SUCCESS; | ||
| 170 | +} | ||
| 171 | + | ||
| 172 | +aclError CompilationManifestParser::ParseSelected( | ||
| 173 | + const std::string& kernelName, bool enableSuperKernel, CompilationManifest& parsedManifest) const | ||
| 174 | +{ | ||
| 175 | + try { | ||
| 176 | + if (borrowedManifest_.at("schema_version").get<std::string>() != SCHEMA_VERSION) { | ||
| 177 | + ASCENDLOGE("Unsupported manifest schema_version; expected %s", SCHEMA_VERSION); | ||
| 178 | + return ACLRTC_ERROR_FAILURE; | ||
| 179 | + } | ||
| 180 | + const auto& kernels = borrowedManifest_.at("kernels"); | ||
| 181 | + if (!kernels.is_array()) { | ||
| 182 | + ASCENDLOGE("Manifest kernels must be an array"); | ||
| 183 | + return ACLRTC_ERROR_FAILURE; | ||
| 184 | + } | ||
| 185 | + const Json* selectedKernel = nullptr; | ||
| 186 | + for (const auto& kernel : kernels) { | ||
| 187 | + if (kernel.at("kernel_name").get<std::string>() == kernelName) { | ||
| 188 | + selectedKernel = &kernel; | ||
| 189 | + break; | ||
| 190 | + } | ||
| 191 | + } | ||
| 192 | + if (selectedKernel == nullptr) { | ||
| 193 | + ASCENDLOGE("Kernel entry '%s' is not present in the manifest", kernelName.c_str()); | ||
| 194 | + return ACLRTC_ERROR_FAILURE; | ||
| 195 | + } | ||
| 196 | + CompilationManifest spec; | ||
| 197 | + aclError result = ParseConstants(*selectedKernel, spec.constants); | ||
| 198 | + if (result != ACLRTC_SUCCESS) { | ||
| 199 | + return result; | ||
| 200 | + } | ||
| 201 | + result = ParseSelectedObjects(*selectedKernel, enableSuperKernel, spec); | ||
| 202 | + if (result != ACLRTC_SUCCESS) { | ||
| 203 | + return result; | ||
| 204 | + } | ||
| 205 | + if (selectedKernel->contains("link_options")) { | ||
| 206 | + spec.linkOptions = selectedKernel->at("link_options").get<std::vector<std::string>>(); | ||
| 207 | + } | ||
| 208 | + parsedManifest = std::move(spec); | ||
| 209 | + return ACLRTC_SUCCESS; | ||
| 210 | + } catch (const nlohmann::json::exception& error) { | ||
| 211 | + ASCENDLOGE("Invalid manifest fields for kernel '%s': %s", kernelName.c_str(), error.what()); | ||
| 212 | + return ACLRTC_ERROR_FAILURE; | ||
| 213 | + } | ||
| 214 | +} | ||
| 215 | + | ||
| 216 | +} // namespace aclrtc | ||
| 217 | +} // namespace ascendc | ||
| @@ -0,0 +1,41 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2026 Huawei Technologies Co., Ltd. | ||
| 3 | + * This program is free software, you can redistribute it and/or modify it under the terms and conditions of | ||
| 4 | + * CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 5 | + * Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 6 | + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, | ||
| 7 | + * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | + * See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | + */ | ||
| 10 | + | ||
| 11 | + | ||
| 12 | + | ||
| 13 | + | ||
| 14 | + | ||
| 15 | + | ||
| 16 | + | ||
| 17 | +namespace ascendc { | ||
| 18 | +namespace aclrtc { | ||
| 19 | + | ||
| 20 | +class CompilationManifestParser final { | ||
| 21 | +public: | ||
| 22 | + explicit CompilationManifestParser(const nlohmann::json& manifest) : borrowedManifest_(manifest) {} | ||
| 23 | + aclError ParseSelected(const std::string& kernelName, bool enableSuperKernel, CompilationManifest& result) const; | ||
| 24 | + | ||
| 25 | +private: | ||
| 26 | + aclError ParseConstants(const nlohmann::json& kernel, std::vector<ManifestConstant>& constants) const; | ||
| 27 | + aclError ExpandOptionsReference( | ||
| 28 | + const std::string& argument, const std::string& location, std::vector<std::string>& arguments) const; | ||
| 29 | + aclError ParseCommand( | ||
| 30 | + const nlohmann::json& command, const std::string& objectName, ManifestObjectKind objectKind, size_t index, | ||
| 31 | + ManifestCommand& result) const; | ||
| 32 | + aclError ParseSelectedObjects( | ||
| 33 | + const nlohmann::json& kernel, bool enableSuperKernel, CompilationManifest& result) const; | ||
| 34 | + | ||
| 35 | + const nlohmann::json& borrowedManifest_; | ||
| 36 | +}; | ||
| 37 | + | ||
| 38 | +} // namespace aclrtc | ||
| 39 | +} // namespace ascendc | ||
| 40 | + | ||
| 41 | + | ||
| @@ -68,11 +68,10 @@ aclError CompilationPlanExecutor::ExecuteCompilationCommand( | |||
| 68 | const CompilationCommand& compilationCommand, ProcessExecutorResult& executorResult) const | 68 | const CompilationCommand& compilationCommand, ProcessExecutorResult& executorResult) const |
| 69 | { | 69 | { |
| 70 | ProcessExecutorRequest executorRequest; | 70 | ProcessExecutorRequest executorRequest; |
| 71 | - executorRequest.arguments.reserve(compilationCommand.commandArguments.size() + 1U); | 71 | + executorRequest.arguments.reserve(compilationCommand.arguments.size() + 1U); |
| 72 | executorRequest.arguments.emplace_back(compilationCommand.executablePath.string()); | 72 | executorRequest.arguments.emplace_back(compilationCommand.executablePath.string()); |
| 73 | executorRequest.arguments.insert( | 73 | executorRequest.arguments.insert( |
| 74 | - executorRequest.arguments.end(), compilationCommand.commandArguments.begin(), | 74 | + executorRequest.arguments.end(), compilationCommand.arguments.begin(), compilationCommand.arguments.end()); |
| 75 | - compilationCommand.commandArguments.end()); | ||
| 76 | executorRequest.mirroredOutputLogFilePath = specializationDiagnostics_.GetCompilationLogFilePath(); | 75 | executorRequest.mirroredOutputLogFilePath = specializationDiagnostics_.GetCompilationLogFilePath(); |
| 77 | executorRequest.executionTimeout = compilationCommand.commandKind == CompilationCommandKind::Compile ? | 76 | executorRequest.executionTimeout = compilationCommand.commandKind == CompilationCommandKind::Compile ? |
| 78 | commandExecutionLimits_.compileCommandTimeout : | 77 | commandExecutionLimits_.compileCommandTimeout : |
| @@ -24,29 +24,8 @@ namespace ascendc { | |||
| 24 | namespace aclrtc { | 24 | namespace aclrtc { |
| 25 | namespace { | 25 | namespace { |
| 26 | namespace fs = boost::filesystem; | 26 | namespace fs = boost::filesystem; |
| 27 | -using Json = nlohmann::json; | ||
| 28 | - | ||
| 29 | -constexpr char SUPPORTED_MANIFEST_SCHEMA_VERSION[] = "1.0"; | ||
| 30 | -constexpr char OPTIONS_REFERENCE_PREFIX[] = "${options:"; | ||
| 31 | constexpr char ENVIRONMENT_REFERENCE_PREFIX[] = "${env:"; | 27 | constexpr char ENVIRONMENT_REFERENCE_PREFIX[] = "${env:"; |
| 32 | 28 | ||
| 33 | -enum class ManifestObjectKind : uint32_t { | ||
| 34 | - Basic, | ||
| 35 | - SuperKernel, | ||
| 36 | -}; | ||
| 37 | - | ||
| 38 | -struct SelectedManifestObject { | ||
| 39 | - const Json* manifestObject{nullptr}; | ||
| 40 | - ManifestObjectKind objectKind{ManifestObjectKind::Basic}; | ||
| 41 | -}; | ||
| 42 | - | ||
| 43 | -struct ManifestExpansionContext { | ||
| 44 | - const Json& resourceManifest; | ||
| 45 | - const fs::path& resourceWorktreePath; | ||
| 46 | - const fs::path& outputDirectoryPath; | ||
| 47 | - const fs::path& externalSourceDirectoryPath; | ||
| 48 | -}; | ||
| 49 | - | ||
| 50 | void ReplaceAllLiteralOccurrences(std::string& text, const std::string& literalText, const std::string& replacementText) | 29 | void ReplaceAllLiteralOccurrences(std::string& text, const std::string& literalText, const std::string& replacementText) |
| 51 | { | 30 | { |
| 52 | size_t occurrencePosition = 0U; | 31 | size_t occurrencePosition = 0U; |
| @@ -99,66 +78,6 @@ bool ExpandEnvironmentVariablePlaceholders( | |||
| 99 | return true; | 78 | return true; |
| 100 | } | 79 | } |
| 101 | 80 | ||
| 102 | -bool ExpandPathAndEnvironmentPlaceholders( | ||
| 103 | - const std::string& manifestText, const std::string& manifestValueLocation, | ||
| 104 | - const ManifestExpansionContext& expansionContext, std::string& resolvedText) | ||
| 105 | -{ | ||
| 106 | - std::string pathResolvedText = manifestText; | ||
| 107 | - ReplaceAllLiteralOccurrences(pathResolvedText, "${resource}", expansionContext.resourceWorktreePath.string()); | ||
| 108 | - ReplaceAllLiteralOccurrences(pathResolvedText, "${output}", expansionContext.outputDirectoryPath.string()); | ||
| 109 | - ReplaceAllLiteralOccurrences( | ||
| 110 | - pathResolvedText, "${source_file_path}", expansionContext.externalSourceDirectoryPath.string()); | ||
| 111 | - return ExpandEnvironmentVariablePlaceholders(pathResolvedText, manifestValueLocation, resolvedText); | ||
| 112 | -} | ||
| 113 | - | ||
| 114 | -bool ParseWholeArgumentOptionsPlaceholder(const std::string& manifestArgument, std::string& optionName) | ||
| 115 | -{ | ||
| 116 | - if (manifestArgument.compare(0, sizeof(OPTIONS_REFERENCE_PREFIX) - 1U, OPTIONS_REFERENCE_PREFIX) != 0 || | ||
| 117 | - manifestArgument.size() <= sizeof(OPTIONS_REFERENCE_PREFIX) || manifestArgument.back() != '}') { | ||
| 118 | - return false; | ||
| 119 | - } | ||
| 120 | - optionName = manifestArgument.substr( | ||
| 121 | - sizeof(OPTIONS_REFERENCE_PREFIX) - 1U, manifestArgument.size() - sizeof(OPTIONS_REFERENCE_PREFIX)); | ||
| 122 | - return !optionName.empty(); | ||
| 123 | -} | ||
| 124 | - | ||
| 125 | -aclError ExpandManifestArgument( | ||
| 126 | - const std::string& manifestArgument, const std::string& argumentLocation, | ||
| 127 | - const ManifestExpansionContext& expansionContext, std::vector<std::string>& expandedArguments) | ||
| 128 | -{ | ||
| 129 | - std::string optionName; | ||
| 130 | - if (!ParseWholeArgumentOptionsPlaceholder(manifestArgument, optionName)) { | ||
| 131 | - std::string resolvedArgument; | ||
| 132 | - if (!ExpandPathAndEnvironmentPlaceholders( | ||
| 133 | - manifestArgument, argumentLocation, expansionContext, resolvedArgument)) { | ||
| 134 | - return ACLRTC_ERROR_FAILURE; | ||
| 135 | - } | ||
| 136 | - expandedArguments.emplace_back(std::move(resolvedArgument)); | ||
| 137 | - return ACLRTC_SUCCESS; | ||
| 138 | - } | ||
| 139 | - | ||
| 140 | - const auto optionTable = expansionContext.resourceManifest.find("options"); | ||
| 141 | - if (optionTable == expansionContext.resourceManifest.end() || !optionTable->is_object() || | ||
| 142 | - optionTable->find(optionName) == optionTable->end()) { | ||
| 143 | - ASCENDLOGE( | ||
| 144 | - "Manifest value %s references undefined options key '%s'; define this key in the top-level options " | ||
| 145 | - "object and regenerate the JIT resource", | ||
| 146 | - argumentLocation.c_str(), optionName.c_str()); | ||
| 147 | - return ACLRTC_ERROR_FAILURE; | ||
| 148 | - } | ||
| 149 | - const std::vector<std::string> optionArguments = optionTable->at(optionName).get<std::vector<std::string>>(); | ||
| 150 | - for (size_t optionIndex = 0U; optionIndex < optionArguments.size(); ++optionIndex) { | ||
| 151 | - std::string resolvedArgument; | ||
| 152 | - const std::string optionLocation = "options['" + optionName + "'][" + std::to_string(optionIndex) + "]"; | ||
| 153 | - if (!ExpandPathAndEnvironmentPlaceholders( | ||
| 154 | - optionArguments[optionIndex], optionLocation, expansionContext, resolvedArgument)) { | ||
| 155 | - return ACLRTC_ERROR_FAILURE; | ||
| 156 | - } | ||
| 157 | - expandedArguments.emplace_back(std::move(resolvedArgument)); | ||
| 158 | - } | ||
| 159 | - return ACLRTC_SUCCESS; | ||
| 160 | -} | ||
| 161 | - | ||
| 162 | bool IsAbsoluteExecutableRegularFile(const fs::path& executablePath) | 81 | bool IsAbsoluteExecutableRegularFile(const fs::path& executablePath) |
| 163 | { | 82 | { |
| 164 | boost::system::error_code fileError; | 83 | boost::system::error_code fileError; |
| @@ -171,15 +90,14 @@ bool IsMissingPathError(const boost::system::error_code& pathError) noexcept | |||
| 171 | return pathError.value() == ENOENT || pathError.value() == ENOTDIR; | 90 | return pathError.value() == ENOENT || pathError.value() == ENOTDIR; |
| 172 | } | 91 | } |
| 173 | 92 | ||
| 174 | -bool FindSeparatedCompilerOutputOptionPosition( | 93 | +bool FindSeparatedCompilerOutputOptionPosition(const std::vector<std::string>& arguments, size_t& outputOptionPosition) |
| 175 | - const std::vector<std::string>& commandArguments, size_t& outputOptionPosition) | ||
| 176 | { | 94 | { |
| 177 | - for (size_t argumentIndex = 0; argumentIndex < commandArguments.size(); ++argumentIndex) { | 95 | + for (size_t argumentIndex = 0; argumentIndex < arguments.size(); ++argumentIndex) { |
| 178 | - const std::string& argument = commandArguments[argumentIndex]; | 96 | + const std::string& argument = arguments[argumentIndex]; |
| 179 | if (argument != "-o") { | 97 | if (argument != "-o") { |
| 180 | continue; | 98 | continue; |
| 181 | } | 99 | } |
| 182 | - if (argumentIndex + 1U < commandArguments.size() && !commandArguments[argumentIndex + 1U].empty()) { | 100 | + if (argumentIndex + 1U < arguments.size() && !arguments[argumentIndex + 1U].empty()) { |
| 183 | outputOptionPosition = argumentIndex; | 101 | outputOptionPosition = argumentIndex; |
| 184 | return true; | 102 | return true; |
| 185 | } | 103 | } |
| @@ -204,119 +122,54 @@ std::string FormatBytesAsCppInitializerList(const void* constantAddress, uint64_ | |||
| 204 | return encodedBytes.str(); | 122 | return encodedBytes.str(); |
| 205 | } | 123 | } |
| 206 | 124 | ||
| 207 | -aclError BuildConstantSourcePatches( | 125 | +} // namespace |
| 208 | - const Json& selectedKernel, const NormalizedKernelSpecializationRequest& specializationRequest, | ||
| 209 | - const ManifestExpansionContext& expansionContext, std::vector<KernelSourcePatch>& sourcePatches) | ||
| 210 | -{ | ||
| 211 | - const auto constantInfos = selectedKernel.find("constant_infos"); | ||
| 212 | - if (constantInfos == selectedKernel.end() || constantInfos->empty()) { | ||
| 213 | - ASCENDLOGE("Selected kernel must contain at least one constant_info for static compilation; regenerate the JIT " | ||
| 214 | - "resource with its static constant metadata"); | ||
| 215 | - return ACLRTC_ERROR_FAILURE; | ||
| 216 | - } | ||
| 217 | - for (size_t constantIndex = 0U; constantIndex < constantInfos->size(); ++constantIndex) { | ||
| 218 | - const Json& constantInfo = constantInfos->at(constantIndex); | ||
| 219 | - const uint64_t constantArgumentIndex = constantInfo.at("parameter_index").get<uint64_t>(); | ||
| 220 | - const uint64_t requiredConstantByteCount = constantInfo.at("byte_size").get<uint64_t>(); | ||
| 221 | - if (specializationRequest.borrowedKernelArgumentDataPointers == nullptr || | ||
| 222 | - specializationRequest.borrowedKernelArgumentByteCounts == nullptr) { | ||
| 223 | - ASCENDLOGE( | ||
| 224 | - "constant parameter_index %llu requires argsAddr and argsBytes; set both request arrays with at " | ||
| 225 | - "least argsCount entries", | ||
| 226 | - static_cast<unsigned long long>(constantArgumentIndex)); | ||
| 227 | - return ACLRTC_ERROR_INVALID_INPUT; | ||
| 228 | - } | ||
| 229 | - if (constantArgumentIndex >= specializationRequest.kernelArgumentCount) { | ||
| 230 | - ASCENDLOGE( | ||
| 231 | - "constant parameter_index %llu is outside argsCount %llu; set argsCount greater than %llu and " | ||
| 232 | - "provide matching argsAddr and argsBytes entries", | ||
| 233 | - static_cast<unsigned long long>(constantArgumentIndex), | ||
| 234 | - static_cast<unsigned long long>(specializationRequest.kernelArgumentCount), | ||
| 235 | - static_cast<unsigned long long>(constantArgumentIndex)); | ||
| 236 | - return ACLRTC_ERROR_INVALID_INPUT; | ||
| 237 | - } | ||
| 238 | - if (specializationRequest.borrowedKernelArgumentDataPointers[constantArgumentIndex] == nullptr) { | ||
| 239 | - ASCENDLOGE( | ||
| 240 | - "argsAddr[%llu] must not be null for a static constant; set it to the constant data buffer", | ||
| 241 | - static_cast<unsigned long long>(constantArgumentIndex)); | ||
| 242 | - return ACLRTC_ERROR_INVALID_INPUT; | ||
| 243 | - } | ||
| 244 | - const uint64_t suppliedConstantByteCount = | ||
| 245 | - specializationRequest.borrowedKernelArgumentByteCounts[constantArgumentIndex]; | ||
| 246 | - if (suppliedConstantByteCount != requiredConstantByteCount) { | ||
| 247 | - ASCENDLOGE( | ||
| 248 | - "argsBytes[%llu]=%llu does not match required byte_size %llu; set argsBytes[%llu] to %llu", | ||
| 249 | - static_cast<unsigned long long>(constantArgumentIndex), | ||
| 250 | - static_cast<unsigned long long>(suppliedConstantByteCount), | ||
| 251 | - static_cast<unsigned long long>(requiredConstantByteCount), | ||
| 252 | - static_cast<unsigned long long>(constantArgumentIndex), | ||
| 253 | - static_cast<unsigned long long>(requiredConstantByteCount)); | ||
| 254 | - return ACLRTC_ERROR_INVALID_INPUT; | ||
| 255 | - } | ||
| 256 | 126 | ||
| 257 | - std::string resolvedTargetFilePath; | 127 | +bool KernelCompilationPlanBuilder::ExpandPathAndEnvironmentReferences( |
| 258 | - const std::string constantFileLocation = "constant_infos[" + std::to_string(constantIndex) + "].file"; | 128 | + const std::string& text, const std::string& location, std::string& resolvedText) const |
| 259 | - if (!ExpandPathAndEnvironmentPlaceholders( | 129 | +{ |
| 260 | - constantInfo.at("file").get<std::string>(), constantFileLocation, expansionContext, | 130 | + std::string pathResolvedText = text; |
| 261 | - resolvedTargetFilePath)) { | 131 | + ReplaceAllLiteralOccurrences(pathResolvedText, "${resource}", resourceWorktreePath_.string()); |
| 132 | + ReplaceAllLiteralOccurrences(pathResolvedText, "${output}", outputDirectoryPath_.string()); | ||
| 133 | + ReplaceAllLiteralOccurrences(pathResolvedText, "${source_file_path}", externalSourceDirectoryPath_.string()); | ||
| 134 | + return ExpandEnvironmentVariablePlaceholders(pathResolvedText, location, resolvedText); | ||
| 135 | +} | ||
| 136 | + | ||
| 137 | +aclError KernelCompilationPlanBuilder::BuildConstantSourcePatches(KernelCompilationPlan& plan) const | ||
| 138 | +{ | ||
| 139 | + auto constants = borrowedManifest_.constants; | ||
| 140 | + std::vector<KernelSourcePatch> patches; | ||
| 141 | + for (ManifestConstant& constant : constants) { | ||
| 142 | + if (!constant.BindArgument( | ||
| 143 | + specializationRequest_.kernelArgumentCount, specializationRequest_.borrowedKernelArgumentDataPointers, | ||
| 144 | + specializationRequest_.borrowedKernelArgumentByteCounts)) { | ||
| 145 | + return ACLRTC_ERROR_INVALID_INPUT; | ||
| 146 | + } | ||
| 147 | + std::string targetFile; | ||
| 148 | + if (!ExpandPathAndEnvironmentReferences(constant.GetTargetFile(), constant.GetName(), targetFile)) { | ||
| 262 | return ACLRTC_ERROR_FAILURE; | 149 | return ACLRTC_ERROR_FAILURE; |
| 263 | } | 150 | } |
| 264 | - sourcePatches.push_back( | 151 | + patches.push_back({targetFile, constant.GetTemplateText(), {}}); |
| 265 | - {resolvedTargetFilePath, constantInfo.at("template").get<std::string>(), | ||
| 266 | - FormatBytesAsCppInitializerList( | ||
| 267 | - specializationRequest.borrowedKernelArgumentDataPointers[constantArgumentIndex], | ||
| 268 | - requiredConstantByteCount)}); | ||
| 269 | } | 152 | } |
| 153 | + // Avoid reading caller-owned buffers if any constant binding or target expansion fails. | ||
| 154 | + for (size_t index = 0; index < constants.size(); ++index) { | ||
| 155 | + patches[index].replacementText = | ||
| 156 | + FormatBytesAsCppInitializerList(constants[index].GetBoundData(), constants[index].GetBoundByteSize()); | ||
| 157 | + } | ||
| 158 | + plan.sourcePatches = std::move(patches); | ||
| 270 | return ACLRTC_SUCCESS; | 159 | return ACLRTC_SUCCESS; |
| 271 | } | 160 | } |
| 272 | 161 | ||
| 273 | -aclError BuildManifestCommand( | 162 | +aclError KernelCompilationPlanBuilder::BindManifestCommand( |
| 274 | - const Json& manifestCommand, const SelectedManifestObject& selectedObject, size_t commandIndex, | 163 | + const ManifestCommand& spec, CompilationCommand& compilationCommand) const |
| 275 | - const NormalizedKernelSpecializationRequest& specializationRequest, | ||
| 276 | - const ManifestExpansionContext& expansionContext, CompilationCommand& compilationCommand) | ||
| 277 | { | 164 | { |
| 278 | - const std::string manifestObjectName = selectedObject.manifestObject->at("object_name").get<std::string>(); | 165 | + compilationCommand.commandKind = spec.commandKind; |
| 279 | - const std::string commandType = manifestCommand.at("type").get<std::string>(); | 166 | + compilationCommand.parallelStage = spec.parallelStage; |
| 280 | - if (commandType == "compile") { | 167 | + compilationCommand.diagnosticLabel = spec.diagnosticLabel; |
| 281 | - compilationCommand.commandKind = CompilationCommandKind::Compile; | 168 | + std::string executable; |
| 282 | - } else if (commandType == "objcopy") { | 169 | + if (!ExpandPathAndEnvironmentReferences(spec.executable, spec.diagnosticLabel, executable)) { |
| 283 | - compilationCommand.commandKind = CompilationCommandKind::ObjectCopy; | ||
| 284 | - } else { | ||
| 285 | - ASCENDLOGE( | ||
| 286 | - "Manifest object %s command[%zu] has unsupported type '%s'; regenerate the JIT resource using a " | ||
| 287 | - "command type supported by ACLRTC", | ||
| 288 | - manifestObjectName.c_str(), commandIndex, commandType.c_str()); | ||
| 289 | return ACLRTC_ERROR_FAILURE; | 170 | return ACLRTC_ERROR_FAILURE; |
| 290 | } | 171 | } |
| 291 | - const auto parallelStage = manifestCommand.find("stage"); | 172 | + compilationCommand.executablePath = std::move(executable); |
| 292 | - if (parallelStage != manifestCommand.end()) { | ||
| 293 | - compilationCommand.parallelStage = parallelStage->get<uint32_t>(); | ||
| 294 | - } | ||
| 295 | - compilationCommand.diagnosticLabel = | ||
| 296 | - manifestObjectName + "/" + commandType + "[" + std::to_string(commandIndex) + "]"; | ||
| 297 | - | ||
| 298 | - const std::vector<std::string> manifestArguments = manifestCommand.at("cmd").get<std::vector<std::string>>(); | ||
| 299 | - if (manifestArguments.empty()) { | ||
| 300 | - ASCENDLOGE( | ||
| 301 | - "Manifest command %s has an empty cmd array; regenerate the JIT resource", | ||
| 302 | - compilationCommand.diagnosticLabel.c_str()); | ||
| 303 | - return ACLRTC_ERROR_FAILURE; | ||
| 304 | - } | ||
| 305 | - std::vector<std::string> expandedExecutable; | ||
| 306 | - aclError result = ExpandManifestArgument( | ||
| 307 | - manifestArguments.front(), compilationCommand.diagnosticLabel + ".cmd[0]", expansionContext, | ||
| 308 | - expandedExecutable); | ||
| 309 | - if (result != ACLRTC_SUCCESS) { | ||
| 310 | - return result; | ||
| 311 | - } | ||
| 312 | - if (expandedExecutable.size() != 1U) { | ||
| 313 | - ASCENDLOGE( | ||
| 314 | - "Manifest command %s executable expanded to %zu argv items; regenerate the JIT resource so cmd[0] " | ||
| 315 | - "resolves to exactly one executable path", | ||
| 316 | - compilationCommand.diagnosticLabel.c_str(), expandedExecutable.size()); | ||
| 317 | - return ACLRTC_ERROR_FAILURE; | ||
| 318 | - } | ||
| 319 | - compilationCommand.executablePath = std::move(expandedExecutable.front()); | ||
| 320 | if (!IsAbsoluteExecutableRegularFile(compilationCommand.executablePath)) { | 173 | if (!IsAbsoluteExecutableRegularFile(compilationCommand.executablePath)) { |
| 321 | ASCENDLOGE( | 174 | ASCENDLOGE( |
| 322 | "Manifest command %s requires an absolute path to an existing executable regular file: path=%s; " | 175 | "Manifest command %s requires an absolute path to an existing executable regular file: path=%s; " |
| @@ -325,111 +178,65 @@ aclError BuildManifestCommand( | |||
| 325 | return ACLRTC_ERROR_FAILURE; | 178 | return ACLRTC_ERROR_FAILURE; |
| 326 | } | 179 | } |
| 327 | 180 | ||
| 328 | - for (size_t argumentIndex = 1U; argumentIndex < manifestArguments.size(); ++argumentIndex) { | 181 | + for (const std::string& argument : spec.arguments) { |
| 329 | - const std::string argumentLocation = | 182 | + std::string resolvedArgument; |
| 330 | - compilationCommand.diagnosticLabel + ".cmd[" + std::to_string(argumentIndex) + "]"; | 183 | + if (!ExpandPathAndEnvironmentReferences(argument, spec.diagnosticLabel, resolvedArgument)) { |
| 331 | - result = ExpandManifestArgument( | 184 | + return ACLRTC_ERROR_FAILURE; |
| 332 | - manifestArguments[argumentIndex], argumentLocation, expansionContext, compilationCommand.commandArguments); | ||
| 333 | - if (result != ACLRTC_SUCCESS) { | ||
| 334 | - return result; | ||
| 335 | } | 185 | } |
| 186 | + compilationCommand.arguments.emplace_back(std::move(resolvedArgument)); | ||
| 336 | } | 187 | } |
| 337 | 188 | ||
| 338 | if (compilationCommand.commandKind == CompilationCommandKind::Compile) { | 189 | if (compilationCommand.commandKind == CompilationCommandKind::Compile) { |
| 339 | size_t outputOptionPosition = 0U; | 190 | size_t outputOptionPosition = 0U; |
| 340 | - if (!FindSeparatedCompilerOutputOptionPosition(compilationCommand.commandArguments, outputOptionPosition)) { | 191 | + if (!FindSeparatedCompilerOutputOptionPosition(compilationCommand.arguments, outputOptionPosition)) { |
| 341 | ASCENDLOGE( | 192 | ASCENDLOGE( |
| 342 | "Manifest compile command %s must contain a valid separated '-o' output option and a non-empty " | 193 | "Manifest compile command %s must contain a valid separated '-o' output option and a non-empty " |
| 343 | "output path; regenerate the JIT resource with '-o' followed by its output path", | 194 | "output path; regenerate the JIT resource with '-o' followed by its output path", |
| 344 | compilationCommand.diagnosticLabel.c_str()); | 195 | compilationCommand.diagnosticLabel.c_str()); |
| 345 | return ACLRTC_ERROR_FAILURE; | 196 | return ACLRTC_ERROR_FAILURE; |
| 346 | } | 197 | } |
| 347 | - const std::vector<std::string>& userOptions = selectedObject.objectKind == ManifestObjectKind::Basic ? | 198 | + const auto& options = spec.objectKind == ManifestObjectKind::Basic ? |
| 348 | - specializationRequest.compilerOptions.basicOptions : | 199 | + specializationRequest_.compilerOptions.basicOptions : |
| 349 | - specializationRequest.compilerOptions.superKernelOptions; | 200 | + specializationRequest_.compilerOptions.superKernelOptions; |
| 350 | - compilationCommand.commandArguments.insert( | 201 | + compilationCommand.arguments.insert( |
| 351 | - compilationCommand.commandArguments.begin() + static_cast<std::ptrdiff_t>(outputOptionPosition), | 202 | + compilationCommand.arguments.begin() + static_cast<std::ptrdiff_t>(outputOptionPosition), options.begin(), |
| 352 | - userOptions.begin(), userOptions.end()); | 203 | + options.end()); |
| 353 | } | 204 | } |
| 354 | return ACLRTC_SUCCESS; | 205 | return ACLRTC_SUCCESS; |
| 355 | } | 206 | } |
| 356 | 207 | ||
| 357 | -aclError SelectManifestObjectsForCompilation( | 208 | +aclError KernelCompilationPlanBuilder::BindLinkCommand( |
| 358 | - const Json& selectedKernel, KernelCompilationVariant compilationVariant, | 209 | + const CompilationManifest& spec, KernelCompilationPlan& plan) const |
| 359 | - std::vector<SelectedManifestObject>& selectedObjects) | ||
| 360 | -{ | ||
| 361 | - bool foundBasicObject = false; | ||
| 362 | - bool foundSuperKernelObject = false; | ||
| 363 | - for (const Json& manifestObject : selectedKernel.at("objects")) { | ||
| 364 | - const std::string objectType = manifestObject.at("object_type").get<std::string>(); | ||
| 365 | - if (objectType == "basic") { | ||
| 366 | - foundBasicObject = true; | ||
| 367 | - selectedObjects.push_back({&manifestObject, ManifestObjectKind::Basic}); | ||
| 368 | - } else if (objectType == "sk") { | ||
| 369 | - foundSuperKernelObject = true; | ||
| 370 | - if (compilationVariant == KernelCompilationVariant::BasicWithSuperKernel) { | ||
| 371 | - selectedObjects.push_back({&manifestObject, ManifestObjectKind::SuperKernel}); | ||
| 372 | - } | ||
| 373 | - } | ||
| 374 | - } | ||
| 375 | - if (!foundBasicObject) { | ||
| 376 | - ASCENDLOGE("Selected kernel does not contain a basic object; regenerate the JIT resource"); | ||
| 377 | - return ACLRTC_ERROR_FAILURE; | ||
| 378 | - } | ||
| 379 | - if (compilationVariant == KernelCompilationVariant::BasicWithSuperKernel && !foundSuperKernelObject) { | ||
| 380 | - ASCENDLOGE("Super-kernel compilation was requested but the selected kernel has no sk object; remove " | ||
| 381 | - "--enable-super-kernel or use a JIT resource that contains an sk object"); | ||
| 382 | - return ACLRTC_ERROR_FAILURE; | ||
| 383 | - } | ||
| 384 | - return ACLRTC_SUCCESS; | ||
| 385 | -} | ||
| 386 | - | ||
| 387 | -aclError BuildLinkCommand( | ||
| 388 | - const Json& selectedKernel, const std::vector<SelectedManifestObject>& selectedObjects, | ||
| 389 | - const ManifestExpansionContext& expansionContext, CompilationCommand& linkCommand, | ||
| 390 | - std::set<fs::path>& requiredOutputDirectories, fs::path& linkedKernelElfPath) | ||
| 391 | { | 210 | { |
| 211 | + CompilationCommand linkCommand; | ||
| 212 | + std::set<fs::path> requiredOutputDirectories{outputDirectoryPath_}; | ||
| 392 | linkCommand.commandKind = CompilationCommandKind::Link; | 213 | linkCommand.commandKind = CompilationCommandKind::Link; |
| 393 | linkCommand.diagnosticLabel = "link"; | 214 | linkCommand.diagnosticLabel = "link"; |
| 394 | std::string linkerPath; | 215 | std::string linkerPath; |
| 395 | - if (!ExpandPathAndEnvironmentPlaceholders( | 216 | + if (!ExpandPathAndEnvironmentReferences( |
| 396 | - "${env:ASCEND_HOME_PATH}/bin/ld.lld", "internal linker executable", expansionContext, linkerPath)) { | 217 | + "${env:ASCEND_HOME_PATH}/bin/ld.lld", "internal linker executable", linkerPath)) { |
| 397 | return ACLRTC_ERROR_FAILURE; | 218 | return ACLRTC_ERROR_FAILURE; |
| 398 | } | 219 | } |
| 399 | linkCommand.executablePath = linkerPath; | 220 | linkCommand.executablePath = linkerPath; |
| 400 | 221 | ||
| 401 | - const auto linkOptions = selectedKernel.find("link_options"); | 222 | + for (const std::string& option : spec.linkOptions) { |
| 402 | - if (linkOptions != selectedKernel.end()) { | 223 | + std::string resolvedOption; |
| 403 | - const std::vector<std::string> configuredLinkOptions = linkOptions->get<std::vector<std::string>>(); | 224 | + if (!ExpandPathAndEnvironmentReferences(option, "link_options", resolvedOption)) { |
| 404 | - for (size_t linkOptionIndex = 0U; linkOptionIndex < configuredLinkOptions.size(); ++linkOptionIndex) { | 225 | + return ACLRTC_ERROR_FAILURE; |
| 405 | - std::string resolvedLinkOption; | ||
| 406 | - const std::string linkOptionLocation = "link_options[" + std::to_string(linkOptionIndex) + "]"; | ||
| 407 | - if (!ExpandPathAndEnvironmentPlaceholders( | ||
| 408 | - configuredLinkOptions[linkOptionIndex], linkOptionLocation, expansionContext, resolvedLinkOption)) { | ||
| 409 | - return ACLRTC_ERROR_FAILURE; | ||
| 410 | - } | ||
| 411 | - linkCommand.commandArguments.emplace_back(std::move(resolvedLinkOption)); | ||
| 412 | } | 226 | } |
| 227 | + linkCommand.arguments.emplace_back(std::move(resolvedOption)); | ||
| 413 | } | 228 | } |
| 414 | - for (const SelectedManifestObject& selectedObject : selectedObjects) { | 229 | + for (const std::string& input : spec.linkInputs) { |
| 415 | - const std::string manifestObjectName = selectedObject.manifestObject->at("object_name").get<std::string>(); | 230 | + std::string resolvedInput; |
| 416 | - const std::vector<std::string> outputs = | 231 | + if (!ExpandPathAndEnvironmentReferences(input, "link_inputs", resolvedInput)) { |
| 417 | - selectedObject.manifestObject->at("outputs").get<std::vector<std::string>>(); | 232 | + return ACLRTC_ERROR_FAILURE; |
| 418 | - for (size_t outputIndex = 0U; outputIndex < outputs.size(); ++outputIndex) { | ||
| 419 | - std::string resolvedOutput; | ||
| 420 | - const std::string outputLocation = manifestObjectName + ".outputs[" + std::to_string(outputIndex) + "]"; | ||
| 421 | - if (!ExpandPathAndEnvironmentPlaceholders( | ||
| 422 | - outputs[outputIndex], outputLocation, expansionContext, resolvedOutput)) { | ||
| 423 | - return ACLRTC_ERROR_FAILURE; | ||
| 424 | - } | ||
| 425 | - linkCommand.commandArguments.emplace_back(resolvedOutput); | ||
| 426 | - requiredOutputDirectories.emplace(fs::path(resolvedOutput).parent_path()); | ||
| 427 | } | 233 | } |
| 234 | + requiredOutputDirectories.emplace(fs::path(resolvedInput).parent_path()); | ||
| 235 | + linkCommand.arguments.emplace_back(std::move(resolvedInput)); | ||
| 428 | } | 236 | } |
| 429 | - linkedKernelElfPath = expansionContext.outputDirectoryPath / "linked_kernel.elf"; | 237 | + plan.linkedKernelElfPath = outputDirectoryPath_ / "linked_kernel.elf"; |
| 430 | - requiredOutputDirectories.emplace(linkedKernelElfPath.parent_path()); | 238 | + linkCommand.arguments.emplace_back("-o"); |
| 431 | - linkCommand.commandArguments.emplace_back("-o"); | 239 | + linkCommand.arguments.emplace_back(plan.linkedKernelElfPath.string()); |
| 432 | - linkCommand.commandArguments.emplace_back(linkedKernelElfPath.string()); | ||
| 433 | if (!IsAbsoluteExecutableRegularFile(linkCommand.executablePath)) { | 240 | if (!IsAbsoluteExecutableRegularFile(linkCommand.executablePath)) { |
| 434 | ASCENDLOGE( | 241 | ASCENDLOGE( |
| 435 | "Linker requires an absolute path to an existing executable regular file: path=%s; verify " | 242 | "Linker requires an absolute path to an existing executable regular file: path=%s; verify " |
| @@ -437,118 +244,73 @@ aclError BuildLinkCommand( | |||
| 437 | linkCommand.executablePath.c_str()); | 244 | linkCommand.executablePath.c_str()); |
| 438 | return ACLRTC_ERROR_FAILURE; | 245 | return ACLRTC_ERROR_FAILURE; |
| 439 | } | 246 | } |
| 247 | + plan.compilationCommands.emplace_back(std::move(linkCommand)); | ||
| 248 | + plan.requiredOutputDirectoryPaths.assign(requiredOutputDirectories.begin(), requiredOutputDirectories.end()); | ||
| 249 | + return ACLRTC_SUCCESS; | ||
| 250 | +} | ||
| 251 | + | ||
| 252 | +aclError KernelCompilationPlanBuilder::CheckResourceWorktreeDirectory() const | ||
| 253 | +{ | ||
| 254 | + if (!resourceWorktreePath_.is_absolute()) { | ||
| 255 | + ASCENDLOGE( | ||
| 256 | + "ResourceRegistry returned a non-absolute worktree path: %s; fix the registry integration", | ||
| 257 | + resourceWorktreePath_.c_str()); | ||
| 258 | + return ACLRTC_ERROR_FAILURE; | ||
| 259 | + } | ||
| 260 | + boost::system::error_code worktreeError; | ||
| 261 | + const bool worktreeIsDirectory = fs::is_directory(resourceWorktreePath_, worktreeError); | ||
| 262 | + if (worktreeError && !IsMissingPathError(worktreeError)) { | ||
| 263 | + ASCENDLOGE( | ||
| 264 | + "Failed to inspect resource worktree: path=%s error=%d message=%s; fix the registry " | ||
| 265 | + "integration", | ||
| 266 | + resourceWorktreePath_.c_str(), worktreeError.value(), worktreeError.message().c_str()); | ||
| 267 | + return ACLRTC_ERROR_FAILURE; | ||
| 268 | + } | ||
| 269 | + if (!worktreeIsDirectory) { | ||
| 270 | + ASCENDLOGE( | ||
| 271 | + "Resource worktree must be an existing directory: path=%s; fix the registry integration", | ||
| 272 | + resourceWorktreePath_.c_str()); | ||
| 273 | + return ACLRTC_ERROR_FAILURE; | ||
| 274 | + } | ||
| 440 | return ACLRTC_SUCCESS; | 275 | return ACLRTC_SUCCESS; |
| 441 | } | 276 | } |
| 442 | -} // namespace | ||
| 443 | 277 | ||
| 444 | KernelCompilationPlanBuilder::KernelCompilationPlanBuilder( | 278 | KernelCompilationPlanBuilder::KernelCompilationPlanBuilder( |
| 445 | - const NormalizedKernelSpecializationRequest& specializationRequest, const nlohmann::json& resourceManifest, | 279 | + const NormalizedKernelSpecializationRequest& specializationRequest, const CompilationManifest& manifest, |
| 446 | fs::path resourceWorktreePath, fs::path externalSourceDirectoryPath) | 280 | fs::path resourceWorktreePath, fs::path externalSourceDirectoryPath) |
| 447 | : specializationRequest_(specializationRequest), | 281 | : specializationRequest_(specializationRequest), |
| 448 | - resourceManifest_(resourceManifest), | 282 | + borrowedManifest_(manifest), |
| 449 | resourceWorktreePath_(std::move(resourceWorktreePath)), | 283 | resourceWorktreePath_(std::move(resourceWorktreePath)), |
| 450 | - externalSourceDirectoryPath_(std::move(externalSourceDirectoryPath)) | 284 | + externalSourceDirectoryPath_(std::move(externalSourceDirectoryPath)), |
| 285 | + outputDirectoryPath_( | ||
| 286 | + resourceWorktreePath_ / (".aclrtc_" + specializationRequest_.specializationSessionId) / "outputs") | ||
| 451 | {} | 287 | {} |
| 452 | 288 | ||
| 453 | aclError KernelCompilationPlanBuilder::BuildCompilationPlan(KernelCompilationPlan& compilationPlan) const | 289 | aclError KernelCompilationPlanBuilder::BuildCompilationPlan(KernelCompilationPlan& compilationPlan) const |
| 454 | { | 290 | { |
| 455 | - try { | 291 | + aclError result = CheckResourceWorktreeDirectory(); |
| 456 | - if (!resourceWorktreePath_.is_absolute()) { | 292 | + if (result != ACLRTC_SUCCESS) { |
| 457 | - ASCENDLOGE( | 293 | + return result; |
| 458 | - "ResourceRegistry returned a non-absolute worktree path: %s; fix the registry integration", | ||
| 459 | - resourceWorktreePath_.c_str()); | ||
| 460 | - return ACLRTC_ERROR_FAILURE; | ||
| 461 | - } | ||
| 462 | - boost::system::error_code worktreeError; | ||
| 463 | - const bool worktreeIsDirectory = fs::is_directory(resourceWorktreePath_, worktreeError); | ||
| 464 | - if (worktreeError && !IsMissingPathError(worktreeError)) { | ||
| 465 | - ASCENDLOGE( | ||
| 466 | - "Failed to inspect resource worktree: path=%s error=%d message=%s; fix the registry " | ||
| 467 | - "integration", | ||
| 468 | - resourceWorktreePath_.c_str(), worktreeError.value(), worktreeError.message().c_str()); | ||
| 469 | - return ACLRTC_ERROR_FAILURE; | ||
| 470 | - } | ||
| 471 | - if (!worktreeIsDirectory) { | ||
| 472 | - ASCENDLOGE( | ||
| 473 | - "Resource worktree must be an existing directory: path=%s; fix the registry integration", | ||
| 474 | - resourceWorktreePath_.c_str()); | ||
| 475 | - return ACLRTC_ERROR_FAILURE; | ||
| 476 | - } | ||
| 477 | - const std::string schemaVersion = resourceManifest_.at("schema_version").get<std::string>(); | ||
| 478 | - if (schemaVersion != SUPPORTED_MANIFEST_SCHEMA_VERSION) { | ||
| 479 | - ASCENDLOGE( | ||
| 480 | - "Unsupported Manifest schema_version '%s'; expected '%s'. Regenerate the JIT resource with a " | ||
| 481 | - "compatible pack tool", | ||
| 482 | - schemaVersion.c_str(), SUPPORTED_MANIFEST_SCHEMA_VERSION); | ||
| 483 | - return ACLRTC_ERROR_FAILURE; | ||
| 484 | - } | ||
| 485 | - | ||
| 486 | - const Json* selectedKernel = nullptr; | ||
| 487 | - for (const Json& kernel : resourceManifest_.at("kernels")) { | ||
| 488 | - if (kernel.at("kernel_name").get<std::string>() == specializationRequest_.kernelName) { | ||
| 489 | - selectedKernel = &kernel; | ||
| 490 | - break; | ||
| 491 | - } | ||
| 492 | - } | ||
| 493 | - if (selectedKernel == nullptr) { | ||
| 494 | - ASCENDLOGE( | ||
| 495 | - "Kernel entry '%s' is not present in JIT resource '%s'; correct kernelEntry or resourceId", | ||
| 496 | - specializationRequest_.kernelName.c_str(), specializationRequest_.resourceId.c_str()); | ||
| 497 | - return ACLRTC_ERROR_FAILURE; | ||
| 498 | - } | ||
| 499 | - | ||
| 500 | - KernelCompilationPlan builtPlan; | ||
| 501 | - const fs::path outputDirectoryPath = | ||
| 502 | - resourceWorktreePath_ / (".aclrtc_" + specializationRequest_.specializationSessionId) / "outputs"; | ||
| 503 | - const ManifestExpansionContext expansionContext{ | ||
| 504 | - resourceManifest_, resourceWorktreePath_, outputDirectoryPath, externalSourceDirectoryPath_}; | ||
| 505 | - aclError result = BuildConstantSourcePatches( | ||
| 506 | - *selectedKernel, specializationRequest_, expansionContext, builtPlan.sourcePatches); | ||
| 507 | - if (result != ACLRTC_SUCCESS) { | ||
| 508 | - return result; | ||
| 509 | - } | ||
| 510 | - | ||
| 511 | - std::vector<SelectedManifestObject> selectedObjects; | ||
| 512 | - result = SelectManifestObjectsForCompilation( | ||
| 513 | - *selectedKernel, specializationRequest_.compilationVariant, selectedObjects); | ||
| 514 | - if (result != ACLRTC_SUCCESS) { | ||
| 515 | - return result; | ||
| 516 | - } | ||
| 517 | - | ||
| 518 | - for (const SelectedManifestObject& selectedObject : selectedObjects) { | ||
| 519 | - const Json& commands = selectedObject.manifestObject->at("commands"); | ||
| 520 | - for (size_t commandIndex = 0U; commandIndex < commands.size(); ++commandIndex) { | ||
| 521 | - CompilationCommand command; | ||
| 522 | - result = BuildManifestCommand( | ||
| 523 | - commands.at(commandIndex), selectedObject, commandIndex, specializationRequest_, expansionContext, | ||
| 524 | - command); | ||
| 525 | - if (result != ACLRTC_SUCCESS) { | ||
| 526 | - return result; | ||
| 527 | - } | ||
| 528 | - builtPlan.compilationCommands.emplace_back(std::move(command)); | ||
| 529 | - } | ||
| 530 | - } | ||
| 531 | - | ||
| 532 | - std::set<fs::path> requiredOutputDirectories{outputDirectoryPath}; | ||
| 533 | - CompilationCommand linkCommand; | ||
| 534 | - result = BuildLinkCommand( | ||
| 535 | - *selectedKernel, selectedObjects, expansionContext, linkCommand, requiredOutputDirectories, | ||
| 536 | - builtPlan.linkedKernelElfPath); | ||
| 537 | - if (result != ACLRTC_SUCCESS) { | ||
| 538 | - return result; | ||
| 539 | - } | ||
| 540 | - builtPlan.compilationCommands.emplace_back(std::move(linkCommand)); | ||
| 541 | - builtPlan.requiredOutputDirectoryPaths.assign( | ||
| 542 | - requiredOutputDirectories.begin(), requiredOutputDirectories.end()); | ||
| 543 | - compilationPlan = std::move(builtPlan); | ||
| 544 | - return ACLRTC_SUCCESS; | ||
| 545 | - } catch (const nlohmann::json::exception& exception) { | ||
| 546 | - ASCENDLOGE( | ||
| 547 | - "Manifest data consumed for kernel entry '%s' is incompatible with schema %s: %s; regenerate the JIT " | ||
| 548 | - "resource with a compatible pack tool", | ||
| 549 | - specializationRequest_.kernelName.c_str(), SUPPORTED_MANIFEST_SCHEMA_VERSION, exception.what()); | ||
| 550 | - return ACLRTC_ERROR_FAILURE; | ||
| 551 | } | 294 | } |
| 295 | + KernelCompilationPlan plan; | ||
| 296 | + for (const ManifestCommand& spec : borrowedManifest_.commands) { | ||
| 297 | + CompilationCommand command; | ||
| 298 | + result = BindManifestCommand(spec, command); | ||
| 299 | + if (result != ACLRTC_SUCCESS) { | ||
| 300 | + return result; | ||
| 301 | + } | ||
| 302 | + plan.compilationCommands.emplace_back(std::move(command)); | ||
| 303 | + } | ||
| 304 | + result = BindLinkCommand(borrowedManifest_, plan); | ||
| 305 | + if (result != ACLRTC_SUCCESS) { | ||
| 306 | + return result; | ||
| 307 | + } | ||
| 308 | + result = BuildConstantSourcePatches(plan); | ||
| 309 | + if (result != ACLRTC_SUCCESS) { | ||
| 310 | + return result; | ||
| 311 | + } | ||
| 312 | + compilationPlan = std::move(plan); | ||
| 313 | + return ACLRTC_SUCCESS; | ||
| 552 | } | 314 | } |
| 553 | 315 | ||
| 554 | } // namespace aclrtc | 316 | } // namespace aclrtc |
| @@ -11,10 +11,9 @@ | |||
| 11 | 11 | ||
| 12 | 12 | ||
| 13 | 13 | ||
| 14 | -#include "kernel_specialization_types.h" | 14 | +#include "compilation_manifest.h" |
| 15 | 15 | ||
| 16 | 16 | ||
| 17 | - | ||
| 18 | 17 | ||
| 19 | namespace ascendc { | 18 | namespace ascendc { |
| 20 | namespace aclrtc { | 19 | namespace aclrtc { |
| @@ -22,16 +21,24 @@ namespace aclrtc { | |||
| 22 | class KernelCompilationPlanBuilder final { | 21 | class KernelCompilationPlanBuilder final { |
| 23 | public: | 22 | public: |
| 24 | KernelCompilationPlanBuilder( | 23 | KernelCompilationPlanBuilder( |
| 25 | - const NormalizedKernelSpecializationRequest& specializationRequest, const nlohmann::json& resourceManifest, | 24 | + const NormalizedKernelSpecializationRequest& specializationRequest, const CompilationManifest& manifest, |
| 26 | boost::filesystem::path resourceWorktreePath, boost::filesystem::path externalSourceDirectoryPath); | 25 | boost::filesystem::path resourceWorktreePath, boost::filesystem::path externalSourceDirectoryPath); |
| 27 | 26 | ||
| 28 | aclError BuildCompilationPlan(KernelCompilationPlan& compilationPlan) const; | 27 | aclError BuildCompilationPlan(KernelCompilationPlan& compilationPlan) const; |
| 29 | 28 | ||
| 30 | private: | 29 | private: |
| 30 | + aclError CheckResourceWorktreeDirectory() const; | ||
| 31 | + bool ExpandPathAndEnvironmentReferences( | ||
| 32 | + const std::string& text, const std::string& location, std::string& resolvedText) const; | ||
| 33 | + aclError BuildConstantSourcePatches(KernelCompilationPlan& plan) const; | ||
| 34 | + aclError BindManifestCommand(const ManifestCommand& spec, CompilationCommand& command) const; | ||
| 35 | + aclError BindLinkCommand(const CompilationManifest& manifest, KernelCompilationPlan& plan) const; | ||
| 36 | + | ||
| 31 | const NormalizedKernelSpecializationRequest& specializationRequest_; | 37 | const NormalizedKernelSpecializationRequest& specializationRequest_; |
| 32 | - const nlohmann::json& resourceManifest_; | 38 | + const CompilationManifest& borrowedManifest_; |
| 33 | boost::filesystem::path resourceWorktreePath_; | 39 | boost::filesystem::path resourceWorktreePath_; |
| 34 | boost::filesystem::path externalSourceDirectoryPath_; | 40 | boost::filesystem::path externalSourceDirectoryPath_; |
| 41 | + boost::filesystem::path outputDirectoryPath_; | ||
| 35 | }; | 42 | }; |
| 36 | 43 | ||
| 37 | } // namespace aclrtc | 44 | } // namespace aclrtc |
| @@ -12,6 +12,7 @@ | |||
| 12 | 12 | ||
| 13 | 13 | ||
| 14 | 14 | ||
| 15 | + | ||
| 15 | 16 | ||
| 16 | 17 | ||
| 17 | 18 | ||
| @@ -203,12 +204,18 @@ aclError KernelSpecializationSession::RunSpecializationWithMaterializedResource( | |||
| 203 | specializationRequest.specializationSessionId); | 204 | specializationRequest.specializationSessionId); |
| 204 | diagnostics.WriteManifestSnapshot(compilationResource.manifest); | 205 | diagnostics.WriteManifestSnapshot(compilationResource.manifest); |
| 205 | 206 | ||
| 206 | - KernelCompilationPlan compilationPlan; | 207 | + CompilationManifest manifest; |
| 207 | aclError specializationStatus = | 208 | aclError specializationStatus = |
| 208 | - KernelCompilationPlanBuilder( | 209 | + CompilationManifestParser(compilationResource.manifest) |
| 209 | - specializationRequest, compilationResource.manifest, compilationWorkspace.GetWorktreePath(), | 210 | + .ParseSelected(specializationRequest.kernelName, specializationRequest.enableSuperKernel, manifest); |
| 210 | - compilationResource.externalSourceDirectoryPath) | 211 | + if (specializationStatus != ACLRTC_SUCCESS) { |
| 211 | - .BuildCompilationPlan(compilationPlan); | 212 | + return ReportSpecializationStatus(specializationRequest, diagnostics, specializationStatus); |
| 213 | + } | ||
| 214 | + KernelCompilationPlan compilationPlan; | ||
| 215 | + specializationStatus = KernelCompilationPlanBuilder( | ||
| 216 | + specializationRequest, manifest, compilationWorkspace.GetWorktreePath(), | ||
| 217 | + compilationResource.externalSourceDirectoryPath) | ||
| 218 | + .BuildCompilationPlan(compilationPlan); | ||
| 212 | if (specializationStatus != ACLRTC_SUCCESS) { | 219 | if (specializationStatus != ACLRTC_SUCCESS) { |
| 213 | return ReportSpecializationStatus(specializationRequest, diagnostics, specializationStatus); | 220 | return ReportSpecializationStatus(specializationRequest, diagnostics, specializationStatus); |
| 214 | } | 221 | } |
| @@ -148,7 +148,7 @@ void KernelSpecializationDiagnostics::AppendCommandToReplayScript(const Compilat | |||
| 148 | } | 148 | } |
| 149 | try { | 149 | try { |
| 150 | std::string replayLine = QuoteArgumentForReplayScript(compilationCommand.executablePath.string()); | 150 | std::string replayLine = QuoteArgumentForReplayScript(compilationCommand.executablePath.string()); |
| 151 | - for (const std::string& argument : compilationCommand.commandArguments) { | 151 | + for (const std::string& argument : compilationCommand.arguments) { |
| 152 | replayLine += " " + QuoteArgumentForReplayScript(argument); | 152 | replayLine += " " + QuoteArgumentForReplayScript(argument); |
| 153 | } | 153 | } |
| 154 | replayLine += '\n'; | 154 | replayLine += '\n'; |
| @@ -198,7 +198,7 @@ aclError NormalizeSuperKernelCompilerOptions( | |||
| 198 | return ACLRTC_SUCCESS; | 198 | return ACLRTC_SUCCESS; |
| 199 | } | 199 | } |
| 200 | 200 | ||
| 201 | - normalizedRequest.compilationVariant = KernelCompilationVariant::BasicWithSuperKernel; | 201 | + normalizedRequest.enableSuperKernel = true; |
| 202 | for (size_t optionIndex = 0U; optionIndex < copiedSuperKernelOptions.size(); ++optionIndex) { | 202 | for (size_t optionIndex = 0U; optionIndex < copiedSuperKernelOptions.size(); ++optionIndex) { |
| 203 | std::string& superKernelOption = copiedSuperKernelOptions[optionIndex]; | 203 | std::string& superKernelOption = copiedSuperKernelOptions[optionIndex]; |
| 204 | if (superKernelOption == SUPER_KERNEL_ENABLE_OPTION) { | 204 | if (superKernelOption == SUPER_KERNEL_ENABLE_OPTION) { |
| @@ -30,11 +30,6 @@ constexpr aclError ACLRTC_ERROR_LINKING = 176004; | |||
| 30 | constexpr aclError ACLRTC_ERROR_OUT_OF_MEMORY = 276001; | 30 | constexpr aclError ACLRTC_ERROR_OUT_OF_MEMORY = 276001; |
| 31 | constexpr aclError ACLRTC_ERROR_FAILURE = 576000; | 31 | constexpr aclError ACLRTC_ERROR_FAILURE = 576000; |
| 32 | 32 | ||
| 33 | -enum class KernelCompilationVariant : uint32_t { | ||
| 34 | - Basic, | ||
| 35 | - BasicWithSuperKernel, | ||
| 36 | -}; | ||
| 37 | - | ||
| 38 | enum class CompilationCommandKind : uint32_t { | 33 | enum class CompilationCommandKind : uint32_t { |
| 39 | Compile, | 34 | Compile, |
| 40 | ObjectCopy, | 35 | ObjectCopy, |
| @@ -51,7 +46,7 @@ struct NormalizedKernelSpecializationRequest { | |||
| 51 | std::string resourceId; | 46 | std::string resourceId; |
| 52 | std::string kernelName; | 47 | std::string kernelName; |
| 53 | boost::filesystem::path outputElfPath; | 48 | boost::filesystem::path outputElfPath; |
| 54 | - KernelCompilationVariant compilationVariant{KernelCompilationVariant::Basic}; | 49 | + bool enableSuperKernel{false}; |
| 55 | KernelCompilerOptions compilerOptions; | 50 | KernelCompilerOptions compilerOptions; |
| 56 | uint64_t kernelArgumentCount{0}; | 51 | uint64_t kernelArgumentCount{0}; |
| 57 | const void* const* borrowedKernelArgumentDataPointers{nullptr}; | 52 | const void* const* borrowedKernelArgumentDataPointers{nullptr}; |
| @@ -69,7 +64,7 @@ struct CompilationCommand { | |||
| 69 | std::optional<uint32_t> parallelStage; | 64 | std::optional<uint32_t> parallelStage; |
| 70 | std::string diagnosticLabel; | 65 | std::string diagnosticLabel; |
| 71 | boost::filesystem::path executablePath; | 66 | boost::filesystem::path executablePath; |
| 72 | - std::vector<std::string> commandArguments; | 67 | + std::vector<std::string> arguments; |
| 73 | }; | 68 | }; |
| 74 | 69 | ||
| 75 | struct KernelCompilationPlan { | 70 | struct KernelCompilationPlan { |
| @@ -39,6 +39,7 @@ add_executable(asc_compile_exporter | |||
| 39 | manifest_bundle_compiler.cpp | 39 | manifest_bundle_compiler.cpp |
| 40 | resource_manifest_validator.cpp | 40 | resource_manifest_validator.cpp |
| 41 | ../common/file_utils.cpp | 41 | ../common/file_utils.cpp |
| 42 | + ../common/manifest_constant.cpp | ||
| 42 | ../common/process_executor.cpp | 43 | ../common/process_executor.cpp |
| 43 | ../common/directory_cleanup_guard.cpp | 44 | ../common/directory_cleanup_guard.cpp |
| 44 | ) | 45 | ) |
| @@ -18,6 +18,7 @@ | |||
| 18 | 18 | ||
| 19 | 19 | ||
| 20 | 20 | ||
| 21 | + | ||
| 21 | 22 | ||
| 22 | 23 | ||
| 23 | namespace ascendc { | 24 | namespace ascendc { |
| @@ -313,49 +314,19 @@ bool ResourceManifestValidator::ValidateOptionArray(const std::string& name) | |||
| 313 | 314 | ||
| 314 | bool ResourceManifestValidator::ValidateConstant(const Json& constant, std::set<std::string>& constantNames) | 315 | bool ResourceManifestValidator::ValidateConstant(const Json& constant, std::set<std::string>& constantNames) |
| 315 | { | 316 | { |
| 316 | - if (!CheckAndLog(constant.is_object(), __LINE__, "invalid constant: expected an object") || | 317 | + ManifestConstant parsed; |
| 317 | - !CheckAndLog(constant.contains("name"), __LINE__, "missing required constant field: name") || | 318 | + if (!parsed.ParseDefinition(constant)) { |
| 318 | - !CheckAndLog( | ||
| 319 | - constant.contains("parameter_index"), __LINE__, "missing required constant field: parameter_index") || | ||
| 320 | - !CheckAndLog(constant.contains("byte_size"), __LINE__, "missing required constant field: byte_size") || | ||
| 321 | - !CheckAndLog(constant.contains("file"), __LINE__, "missing required constant field: file") || | ||
| 322 | - !CheckAndLog(constant.contains("template"), __LINE__, "missing required constant field: template") || | ||
| 323 | - !CheckAndLog(constant.size() == 5U, __LINE__, "invalid constant: expected exactly five fields") || | ||
| 324 | - !CheckAndLog(constant.at("name").is_string(), __LINE__, "invalid constant name: expected a string") || | ||
| 325 | - !CheckAndLog( | ||
| 326 | - !constant.at("name").get_ref<const std::string&>().empty(), __LINE__, | ||
| 327 | - "invalid constant name: expected a nonempty string") || | ||
| 328 | - !CheckAndLog( | ||
| 329 | - constant.at("parameter_index").is_number_unsigned(), __LINE__, | ||
| 330 | - "invalid parameter_index: expected an unsigned integer") || | ||
| 331 | - !CheckAndLog( | ||
| 332 | - constant.at("byte_size").is_number_unsigned(), __LINE__, | ||
| 333 | - "invalid byte_size: expected an unsigned integer") || | ||
| 334 | - !CheckAndLog( | ||
| 335 | - constant.at("byte_size").get<Json::number_unsigned_t>() != 0U, __LINE__, | ||
| 336 | - "invalid byte_size: expected a nonzero value") || | ||
| 337 | - !CheckAndLog(constant.at("file").is_string(), __LINE__, "invalid constant file: expected a string") || | ||
| 338 | - !CheckAndLog(constant.at("template").is_string(), __LINE__, "invalid constant template: expected a string") || | ||
| 339 | - !CheckAndLog( | ||
| 340 | - !constant.at("template").get_ref<const std::string&>().empty(), __LINE__, | ||
| 341 | - "invalid constant template: expected a nonempty string")) { | ||
| 342 | return false; | 319 | return false; |
| 343 | } | 320 | } |
| 344 | - | ||
| 345 | - const std::string name = constant.at("name").get_ref<const std::string&>(); | ||
| 346 | - const std::string file = constant.at("file").get_ref<const std::string&>(); | ||
| 347 | if (!CheckAndLog( | 321 | if (!CheckAndLog( |
| 348 | - file.rfind(std::string(RESOURCE_ROOT_MARKER) + "/", 0U) == 0U, __LINE__, | 322 | + parsed.GetTargetFile().rfind(std::string(RESOURCE_ROOT_MARKER) + "/", 0U) == 0U, __LINE__, |
| 349 | "invalid constant file: expected ${resource}/<relative-path>") || | 323 | "invalid constant file: expected ${resource}/<relative-path>") || |
| 350 | - !ValidateResourceReference(file) || | 324 | + !ValidateResourceReference(parsed.GetTargetFile()) || |
| 351 | - !CheckAndLog(constantNames.insert(name).second, __LINE__, "duplicate constant name: name=" + name)) { | 325 | + !CheckAndLog( |
| 326 | + constantNames.insert(parsed.GetName()).second, __LINE__, | ||
| 327 | + "duplicate constant name: name=" + parsed.GetName())) { | ||
| 352 | return false; | 328 | return false; |
| 353 | } | 329 | } |
| 354 | - | ||
| 355 | - ASCENDLOGD( | ||
| 356 | - "Validated constant: name=%s parameter_index=%llu byte_size=%llu", name.c_str(), | ||
| 357 | - static_cast<unsigned long long>(constant.at("parameter_index").get<Json::number_unsigned_t>()), | ||
| 358 | - static_cast<unsigned long long>(constant.at("byte_size").get<Json::number_unsigned_t>())); | ||
| 359 | return true; | 330 | return true; |
| 360 | } | 331 | } |
| 361 | 332 | ||
| @@ -736,6 +736,7 @@ class ManifestPackageWriter: | |||
| 736 | { | 736 | { |
| 737 | "name": constant_info.name, | 737 | "name": constant_info.name, |
| 738 | "parameter_index": constant_info.parameter_index, | 738 | "parameter_index": constant_info.parameter_index, |
| 739 | + "arg_type": "pointer", | ||
| 739 | "byte_size": constant_info.byte_size, | 740 | "byte_size": constant_info.byte_size, |
| 740 | "file": _resource_placeholder( | 741 | "file": _resource_placeholder( |
| 741 | self._resource_path, | 742 | self._resource_path, |
| @@ -731,6 +731,7 @@ class ManifestPackageWriter: | |||
| 731 | { | 731 | { |
| 732 | "name": constant_info.name, | 732 | "name": constant_info.name, |
| 733 | "parameter_index": constant_info.parameter_index, | 733 | "parameter_index": constant_info.parameter_index, |
| 734 | + "arg_type": "pointer", | ||
| 734 | "byte_size": constant_info.byte_size, | 735 | "byte_size": constant_info.byte_size, |
| 735 | "file": _resource_placeholder( | 736 | "file": _resource_placeholder( |
| 736 | self._resource_path, | 737 | self._resource_path, |
| @@ -0,0 +1,125 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2026 Huawei Technologies Co., Ltd. | ||
| 3 | + * This program is free software, you can redistribute it and/or modify it under the terms and conditions of | ||
| 4 | + * CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 5 | + * Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 6 | + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, | ||
| 7 | + * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | + * See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | + */ | ||
| 10 | + | ||
| 11 | + | ||
| 12 | + | ||
| 13 | + | ||
| 14 | + | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | +namespace ascendc { | ||
| 19 | +namespace { | ||
| 20 | +using Json = nlohmann::json; | ||
| 21 | + | ||
| 22 | +bool ReadNonnegativeInteger(const Json& value, uint64_t& result) | ||
| 23 | +{ | ||
| 24 | + if (!value.is_number_integer() || (!value.is_number_unsigned() && value.get<int64_t>() < 0)) { | ||
| 25 | + return false; | ||
| 26 | + } | ||
| 27 | + result = value.get<uint64_t>(); | ||
| 28 | + return true; | ||
| 29 | +} | ||
| 30 | +} // namespace | ||
| 31 | + | ||
| 32 | +bool ManifestConstant::ParseDefinition(const Json& constant) | ||
| 33 | +{ | ||
| 34 | + if (!constant.is_object()) { | ||
| 35 | + ASCENDLOGE("constant must be an object"); | ||
| 36 | + return false; | ||
| 37 | + } | ||
| 38 | + for (const char* field : {"name", "parameter_index", "file", "template"}) { | ||
| 39 | + if (!constant.contains(field)) { | ||
| 40 | + ASCENDLOGE("Missing required constant field: %s", field); | ||
| 41 | + return false; | ||
| 42 | + } | ||
| 43 | + } | ||
| 44 | + for (const char* field : {"name", "file", "template"}) { | ||
| 45 | + if (!constant.at(field).is_string() || constant.at(field).get_ref<const std::string&>().empty()) { | ||
| 46 | + ASCENDLOGE("Constant field must be a nonempty string: %s", field); | ||
| 47 | + return false; | ||
| 48 | + } | ||
| 49 | + } | ||
| 50 | + ManifestConstant result; | ||
| 51 | + if (!ReadNonnegativeInteger(constant.at("parameter_index"), result.parameterIndex_)) { | ||
| 52 | + ASCENDLOGE("parameter_index must be a nonnegative integer"); | ||
| 53 | + return false; | ||
| 54 | + } | ||
| 55 | + const bool hasArgumentType = constant.contains("arg_type"); | ||
| 56 | + if (hasArgumentType && !constant.at("arg_type").is_string()) { | ||
| 57 | + ASCENDLOGE("arg_type must be a string"); | ||
| 58 | + return false; | ||
| 59 | + } | ||
| 60 | + const std::string argumentType = hasArgumentType ? constant.at("arg_type").get<std::string>() : "struct"; | ||
| 61 | + const bool hasByteSize = constant.contains("byte_size"); | ||
| 62 | + if (argumentType == "pointer") { | ||
| 63 | + uint64_t byteCount = 0U; | ||
| 64 | + if (!hasByteSize || !ReadNonnegativeInteger(constant.at("byte_size"), byteCount) || byteCount == 0U) { | ||
| 65 | + ASCENDLOGE("pointer constant requires a positive integer byte_size"); | ||
| 66 | + return false; | ||
| 67 | + } | ||
| 68 | + result.manifestByteSize_ = byteCount; | ||
| 69 | + } else if (argumentType == "struct") { | ||
| 70 | + if (hasByteSize) { | ||
| 71 | + ASCENDLOGE("struct constant must omit byte_size; size comes from argsBytes"); | ||
| 72 | + return false; | ||
| 73 | + } | ||
| 74 | + } else { | ||
| 75 | + ASCENDLOGE("arg_type must be pointer or struct"); | ||
| 76 | + return false; | ||
| 77 | + } | ||
| 78 | + constexpr size_t requiredFieldCount = 4U; | ||
| 79 | + const size_t expectedFieldCount = requiredFieldCount + (hasArgumentType ? 1U : 0U) + (hasByteSize ? 1U : 0U); | ||
| 80 | + if (constant.size() != expectedFieldCount) { | ||
| 81 | + ASCENDLOGE("constant contains unexpected fields"); | ||
| 82 | + return false; | ||
| 83 | + } | ||
| 84 | + result.name_ = constant.at("name").get<std::string>(); | ||
| 85 | + result.targetFile_ = constant.at("file").get<std::string>(); | ||
| 86 | + result.templateText_ = constant.at("template").get<std::string>(); | ||
| 87 | + result.definitionParsed_ = true; | ||
| 88 | + *this = std::move(result); | ||
| 89 | + return true; | ||
| 90 | +} | ||
| 91 | + | ||
| 92 | +bool ManifestConstant::BindArgument(uint64_t argsCount, const void* const* argsAddr, const uint64_t* argsBytes) | ||
| 93 | +{ | ||
| 94 | + if (!definitionParsed_) { | ||
| 95 | + ASCENDLOGE("Constant definition must be parsed before binding an argument"); | ||
| 96 | + return false; | ||
| 97 | + } | ||
| 98 | + if (parameterIndex_ >= argsCount) { | ||
| 99 | + ASCENDLOGE( | ||
| 100 | + "Constant %s parameter_index %llu is outside argsCount %llu", name_.c_str(), | ||
| 101 | + static_cast<unsigned long long>(parameterIndex_), static_cast<unsigned long long>(argsCount)); | ||
| 102 | + return false; | ||
| 103 | + } | ||
| 104 | + if (argsAddr == nullptr || argsAddr[parameterIndex_] == nullptr) { | ||
| 105 | + ASCENDLOGE( | ||
| 106 | + "Constant %s requires a nonnull argsAddr[%llu]", name_.c_str(), | ||
| 107 | + static_cast<unsigned long long>(parameterIndex_)); | ||
| 108 | + return false; | ||
| 109 | + } | ||
| 110 | + uint64_t byteSize = manifestByteSize_; | ||
| 111 | + if (byteSize == 0U) { | ||
| 112 | + if (argsBytes == nullptr || argsBytes[parameterIndex_] == 0U) { | ||
| 113 | + ASCENDLOGE( | ||
| 114 | + "Constant %s requires nonzero argsBytes[%llu]", name_.c_str(), | ||
| 115 | + static_cast<unsigned long long>(parameterIndex_)); | ||
| 116 | + return false; | ||
| 117 | + } | ||
| 118 | + byteSize = argsBytes[parameterIndex_]; | ||
| 119 | + } | ||
| 120 | + borrowedData_ = argsAddr[parameterIndex_]; | ||
| 121 | + boundByteSize_ = byteSize; | ||
| 122 | + return true; | ||
| 123 | +} | ||
| 124 | + | ||
| 125 | +} // namespace ascendc | ||
| @@ -0,0 +1,46 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2026 Huawei Technologies Co., Ltd. | ||
| 3 | + * This program is free software, you can redistribute it and/or modify it under the terms and conditions of | ||
| 4 | + * CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 5 | + * Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 6 | + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, | ||
| 7 | + * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | + * See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | + */ | ||
| 10 | + | ||
| 11 | + | ||
| 12 | + | ||
| 13 | + | ||
| 14 | + | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | +namespace ascendc { | ||
| 19 | + | ||
| 20 | +class ManifestConstant final { | ||
| 21 | +public: | ||
| 22 | + bool ParseDefinition(const nlohmann::json& constantJson); | ||
| 23 | + bool BindArgument(uint64_t argsCount, const void* const* argsAddr, const uint64_t* argsBytes); | ||
| 24 | + | ||
| 25 | + const std::string& GetName() const { return name_; } | ||
| 26 | + uint64_t GetParameterIndex() const { return parameterIndex_; } | ||
| 27 | + const std::string& GetTargetFile() const { return targetFile_; } | ||
| 28 | + const std::string& GetTemplateText() const { return templateText_; } | ||
| 29 | + const void* GetBoundData() const { return borrowedData_; } | ||
| 30 | + uint64_t GetBoundByteSize() const { return boundByteSize_; } | ||
| 31 | + | ||
| 32 | +private: | ||
| 33 | + bool definitionParsed_{false}; | ||
| 34 | + std::string name_; | ||
| 35 | + uint64_t parameterIndex_{0U}; | ||
| 36 | + // Zero means the byte size must be obtained from the bound argument. | ||
| 37 | + uint64_t manifestByteSize_{0U}; | ||
| 38 | + std::string targetFile_; | ||
| 39 | + std::string templateText_; | ||
| 40 | + const void* borrowedData_{nullptr}; | ||
| 41 | + uint64_t boundByteSize_{0U}; | ||
| 42 | +}; | ||
| 43 | + | ||
| 44 | +} // namespace ascendc | ||
| 45 | + | ||
| 46 | + | ||