@@ -1377,6 +1377,22 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {
13771377 // Populate the tool chains for the offloading devices, if any.
13781378 CreateOffloadingDeviceToolChains (*C, Inputs);
13791379
1380+ // Determine FPGA emulation status.
1381+ if (C->hasOffloadToolChain <Action::OFK_SYCL>()) {
1382+ auto SYCLTCRange = C->getOffloadToolChains <Action::OFK_SYCL>();
1383+ ArgStringList TargetArgs;
1384+ const ToolChain *TC = SYCLTCRange.first ->second ;
1385+ const toolchains::SYCLToolChain *SYCLTC =
1386+ static_cast <const toolchains::SYCLToolChain *>(TC);
1387+ SYCLTC->TranslateBackendTargetArgs (*TranslatedArgs, TargetArgs);
1388+ for (StringRef ArgString : TargetArgs) {
1389+ if (ArgString.equals (" -hardware" ) || ArgString.equals (" -simulation" )) {
1390+ setFPGAEmulationMode (false );
1391+ break ;
1392+ }
1393+ }
1394+ }
1395+
13801396 // Construct the list of abstract actions to perform for this compilation. On
13811397 // MachO targets this uses the driver-driver and universal actions.
13821398 if (TC.getTriple ().isOSBinFormatMachO ())
@@ -4210,11 +4226,13 @@ class OffloadingActionBuilder final {
42104226 Action *FPGAAOTAction;
42114227 constexpr char COL_CODE[] = " Code" ;
42124228 constexpr char COL_ZERO[] = " 0" ;
4213- if (Input->getType () == types::TY_FPGA_AOCR)
4229+ if (Input->getType () == types::TY_FPGA_AOCR ||
4230+ Input->getType () == types::TY_FPGA_AOCR_EMU)
42144231 // Generate AOCX/AOCR
42154232 FPGAAOTAction =
42164233 C.MakeAction <BackendCompileJobAction>(Input, FPGAOutType);
4217- else if (Input->getType () == types::TY_FPGA_AOCX)
4234+ else if (Input->getType () == types::TY_FPGA_AOCX ||
4235+ Input->getType () == types::TY_FPGA_AOCX_EMU)
42184236 FPGAAOTAction = Input;
42194237 else
42204238 llvm_unreachable (" Unexpected FPGA input type." );
@@ -4563,9 +4581,15 @@ class OffloadingActionBuilder final {
45634581 (SYCLLinkTargets || (WrapDeviceOnlyBinary && !SYCLfpgaTriple));
45644582
45654583 // Set the FPGA output type based on command line (-fsycl-link).
4566- if (auto * A = C.getInputArgs ().getLastArg (options::OPT_fsycl_link_EQ))
4584+ if (auto *A = C.getInputArgs ().getLastArg (options::OPT_fsycl_link_EQ)) {
45674585 FPGAOutType = (A->getValue () == StringRef (" early" ))
4568- ? types::TY_FPGA_AOCR : types::TY_FPGA_AOCX;
4586+ ? types::TY_FPGA_AOCR
4587+ : types::TY_FPGA_AOCX;
4588+ if (C.getDriver ().isFPGAEmulationMode ())
4589+ FPGAOutType = (A->getValue () == StringRef (" early" ))
4590+ ? types::TY_FPGA_AOCR_EMU
4591+ : types::TY_FPGA_AOCX_EMU;
4592+ }
45694593
45704594 // Populate FPGA static archives that could contain dep files to be
45714595 // incorporated into the aoc compilation
@@ -4709,6 +4733,46 @@ class OffloadingActionBuilder final {
47094733 return C.MakeAction <OffloadAction>(HDep, DDeps);
47104734 }
47114735
4736+ // Update Input action to reflect FPGA device archive specifics based
4737+ // on archive contents.
4738+ bool updateInputForFPGA (Action *&A, const Arg *InputArg,
4739+ DerivedArgList &Args) {
4740+ std::string InputName = InputArg->getAsString (Args);
4741+ const Driver &D = C.getDriver ();
4742+ bool IsFPGAEmulation = D.isFPGAEmulationMode ();
4743+ // Only check for FPGA device information when using fpga SubArch.
4744+ if (A->getType () == types::TY_Object && isObjectFile (InputName))
4745+ return true ;
4746+
4747+ auto ArchiveTypeMismatch = [&D, &InputName](bool EmitDiag) {
4748+ if (EmitDiag)
4749+ D.Diag (clang::diag::warn_drv_mismatch_fpga_archive) << InputName;
4750+ };
4751+ // Type FPGA aoco is a special case for static archives
4752+ if (A->getType () == types::TY_FPGA_AOCO) {
4753+ if (!hasFPGABinary (C, InputName, types::TY_FPGA_AOCO))
4754+ return false ;
4755+ A = C.MakeAction <InputAction>(*InputArg, types::TY_FPGA_AOCO);
4756+ return true ;
4757+ }
4758+
4759+ SmallVector<std::pair<types::ID, bool >, 4 > FPGAAOCTypes = {
4760+ {types::TY_FPGA_AOCX, false },
4761+ {types::TY_FPGA_AOCR, false },
4762+ {types::TY_FPGA_AOCX_EMU, true },
4763+ {types::TY_FPGA_AOCR_EMU, true }};
4764+ for (const auto &ArchiveType : FPGAAOCTypes) {
4765+ bool BinaryFound = hasFPGABinary (C, InputName, ArchiveType.first );
4766+ if (BinaryFound && ArchiveType.second == IsFPGAEmulation) {
4767+ // Binary matches check and emulation type, we keep this one.
4768+ A = C.MakeAction <InputAction>(*InputArg, ArchiveType.first );
4769+ return true ;
4770+ }
4771+ ArchiveTypeMismatch (BinaryFound && ArchiveType.second != IsFPGAEmulation);
4772+ }
4773+ return true ;
4774+ }
4775+
47124776 // / Generate an action that adds a host dependence to a device action. The
47134777 // / results will be kept in this action builder. Return true if an error was
47144778 // / found.
@@ -4719,7 +4783,8 @@ class OffloadingActionBuilder final {
47194783 return true ;
47204784
47214785 // An FPGA AOCX input does not have a host dependence to the unbundler
4722- if (HostAction->getType () == types::TY_FPGA_AOCX)
4786+ if (HostAction->getType () == types::TY_FPGA_AOCX ||
4787+ HostAction->getType () == types::TY_FPGA_AOCX_EMU)
47234788 return false ;
47244789
47254790 // If we are supporting bundling/unbundling and the current action is an
@@ -4734,7 +4799,6 @@ class OffloadingActionBuilder final {
47344799 !InputArg->getOption ().hasFlag (options::LinkerInput) &&
47354800 (!types::isSrcFile (HostAction->getType ()) ||
47364801 HostAction->getType () == types::TY_PP_HIP)) {
4737- std::string InputName = InputArg->getAsString (Args);
47384802 ActionList HostActionList;
47394803 Action *A (HostAction);
47404804 // Only check for FPGA device information when using fpga SubArch.
@@ -4743,22 +4807,13 @@ class OffloadingActionBuilder final {
47434807 HasFPGATarget |= TI->second ->getTriple ().getSubArch () ==
47444808 llvm::Triple::SPIRSubArch_fpga;
47454809 bool isArchive = !(HostAction->getType () == types::TY_Object &&
4746- isObjectFile (InputName ));
4810+ isObjectFile (InputArg-> getAsString (Args) ));
47474811 if (!HasFPGATarget && isArchive &&
47484812 HostAction->getType () == types::TY_FPGA_AOCO)
47494813 // Archive with Non-FPGA target with AOCO type should not be unbundled.
47504814 return false ;
4751- if (HasFPGATarget && isArchive) {
4752- // Type FPGA aoco is a special case for -foffload-static-lib.
4753- if (HostAction->getType () == types::TY_FPGA_AOCO) {
4754- if (!hasFPGABinary (C, InputName, types::TY_FPGA_AOCO))
4755- return false ;
4756- A = C.MakeAction <InputAction>(*InputArg, types::TY_FPGA_AOCO);
4757- } else if (hasFPGABinary (C, InputName, types::TY_FPGA_AOCX))
4758- A = C.MakeAction <InputAction>(*InputArg, types::TY_FPGA_AOCX);
4759- else if (hasFPGABinary (C, InputName, types::TY_FPGA_AOCR))
4760- A = C.MakeAction <InputAction>(*InputArg, types::TY_FPGA_AOCR);
4761- }
4815+ if (HasFPGATarget && !updateInputForFPGA (A, InputArg, Args))
4816+ return false ;
47624817 auto UnbundlingHostAction = C.MakeAction <OffloadUnbundlingJobAction>(A);
47634818 UnbundlingHostAction->registerDependentActionInfo (
47644819 C.getSingleOffloadToolChain <Action::OFK_Host>(),
@@ -4795,7 +4850,8 @@ class OffloadingActionBuilder final {
47954850 if ((OffloadKind == Action::OFK_None && CanUseBundler) ||
47964851 (HasFPGATarget && ((Args.hasArg (options::OPT_fsycl_link_EQ) &&
47974852 HostAction->getType () == types::TY_Object) ||
4798- HostAction->getType () == types::TY_FPGA_AOCX)))
4853+ HostAction->getType () == types::TY_FPGA_AOCX ||
4854+ HostAction->getType () == types::TY_FPGA_AOCX_EMU)))
47994855 if (auto *UA = dyn_cast<OffloadUnbundlingJobAction>(HostAction))
48004856 HostAction = UA->getInputs ().back ();
48014857
@@ -5245,8 +5301,13 @@ void Driver::BuildActions(Compilation &C, DerivedArgList &Args,
52455301 continue ;
52465302 // FPGA AOCX/AOCR files are archives, but we do not want to unbundle them
52475303 // here as they have already been unbundled and processed for linking.
5304+ // TODO: The multiple binary checks for FPGA types getting a little out
5305+ // of hand. Improve this by doing a single scan of the args and holding
5306+ // that in a data structure for reference.
52485307 if (hasFPGABinary (C, LA.str (), types::TY_FPGA_AOCX) ||
5249- hasFPGABinary (C, LA.str (), types::TY_FPGA_AOCR))
5308+ hasFPGABinary (C, LA.str (), types::TY_FPGA_AOCR) ||
5309+ hasFPGABinary (C, LA.str (), types::TY_FPGA_AOCX_EMU) ||
5310+ hasFPGABinary (C, LA.str (), types::TY_FPGA_AOCR_EMU))
52505311 continue ;
52515312 // For offload-static-libs we add an unbundling action for each static
52525313 // archive which produces list files with extracted objects. Device lists
@@ -5279,7 +5340,9 @@ void Driver::BuildActions(Compilation &C, DerivedArgList &Args,
52795340 };
52805341 if (auto *IA = dyn_cast<InputAction>(LI)) {
52815342 if (IA->getType () == types::TY_FPGA_AOCR ||
5282- IA->getType () == types::TY_FPGA_AOCX) {
5343+ IA->getType () == types::TY_FPGA_AOCX ||
5344+ IA->getType () == types::TY_FPGA_AOCR_EMU ||
5345+ IA->getType () == types::TY_FPGA_AOCX_EMU) {
52835346 // Add to unbundler.
52845347 UnbundlerInput = LI;
52855348 } else {
@@ -6249,7 +6312,8 @@ InputInfo Driver::BuildJobsForActionNoCache(
62496312 TI = types::TY_TempAOCOfilelist;
62506313 Ext = " txt" ;
62516314 }
6252- if (JA->getType () == types::TY_FPGA_AOCR)
6315+ if (JA->getType () == types::TY_FPGA_AOCR ||
6316+ JA->getType () == types::TY_FPGA_AOCR_EMU)
62536317 // AOCR files are always unbundled into a list file.
62546318 TI = types::TY_Tempfilelist;
62556319 } else if (EffectiveTriple.getSubArch () !=
0 commit comments