From 804c4d7b4fc5a33b8e46572a18b92fe1fbbbcbc0 Mon Sep 17 00:00:00 2001 From: Momchil Velikov Date: Mon, 1 Aug 2022 06:48:22 +0100 Subject: [PATCH 01/33] [SimplifyCFG] Allow SimplifyCFG hoisting to skip over non-matching instructions SimplifyCFG does some common code hoisting, which is limited to hoisting a sequence of identical instruction in identical order and stops at the first non-identical instruction. This patch allows hoisting instruction pairs over same-length sequences of non-matching instructions. The linear asymptotic complexity of the algorithm stays the same, there's an extra parameter `simplifycfg-hoist-common-skip-limit` serving to limit compilation time and/or the size of the hoisted live ranges. The patch improves SPECv6/525.x264_r by about 10%. Reviewed By: dmgreen Differential Revision: https://reviews.llvm.org/D129370 --- llvm/lib/Transforms/Utils/SimplifyCFG.cpp | 202 +++++++++---- .../SimplifyCFG/hoist-common-skip-limit.ll | 97 ++++++ .../SimplifyCFG/hoist-common-skip.ll | 277 ++++++++++++++++++ 3 files changed, 515 insertions(+), 61 deletions(-) create mode 100644 llvm/test/Transforms/SimplifyCFG/hoist-common-skip-limit.ll create mode 100644 llvm/test/Transforms/SimplifyCFG/hoist-common-skip.ll diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp index 1806081678a8..1b148aeb794d 100644 --- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp +++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp @@ -115,6 +115,12 @@ static cl::opt HoistCommon("simplifycfg-hoist-common", cl::Hidden, cl::init(true), cl::desc("Hoist common instructions up to the parent block")); +static cl::opt + HoistCommonSkipLimit("simplifycfg-hoist-common-skip-limit", cl::Hidden, + cl::init(20), + cl::desc("Allow reordering across at most this many " + "instructions when hoisting")); + static cl::opt SinkCommon("simplifycfg-sink-common", cl::Hidden, cl::init(true), cl::desc("Sink common instructions down to the end block")); @@ -1430,6 +1436,32 @@ static bool isSafeToHoistInvoke(BasicBlock *BB1, BasicBlock *BB2, return true; } +// Returns true if it is safe to reorder an instruction across preceding +// instructions in a basic block. +static bool isSafeToHoistInstr(Instruction *I, bool ForceNoSideEffects, + bool ForceNoSpeculation) { + // If we have seen an instruction with side effects, it's unsafe to reorder an + // instruction which reads memory or itself has side effects. + if (ForceNoSideEffects && (I->mayReadFromMemory() || I->mayHaveSideEffects())) + return false; + + // Reordering across an instruction which does not necessarily transfer + // control to the next instruction is speculation. + if (ForceNoSpeculation && !isSafeToSpeculativelyExecute(I)) + return false; + + // It's also unsafe/illegal to hoist an instruction above its instruction + // operands + BasicBlock *BB = I->getParent(); + for (Value *Op : I->operands()) { + if (auto *J = dyn_cast(Op)) + if (J->getParent() == BB) + return false; + } + + return true; +} + static bool passingValueIsAlwaysUndefined(Value *V, Instruction *I, bool PtrValueMayBeModified = false); /// Given a conditional branch that goes to BB1 and BB2, hoist any common code @@ -1444,7 +1476,8 @@ bool SimplifyCFGOpt::HoistThenElseCodeToIf(BranchInst *BI, // instructions in the two blocks. In particular, we don't want to get into // O(M*N) situations here where M and N are the sizes of BB1 and BB2. As // such, we currently just scan for obviously identical instructions in an - // identical order. + // identical order, possibly separated by the same number of non-identical + // instructions. BasicBlock *BB1 = BI->getSuccessor(0); // The true destination. BasicBlock *BB2 = BI->getSuccessor(1); // The false destination @@ -1467,7 +1500,7 @@ bool SimplifyCFGOpt::HoistThenElseCodeToIf(BranchInst *BI, while (isa(I2)) I2 = &*BB2_Itr++; } - if (isa(I1) || !I1->isIdenticalToWhenDefined(I2)) + if (isa(I1)) return false; BasicBlock *BIParent = BI->getParent(); @@ -1493,75 +1526,122 @@ bool SimplifyCFGOpt::HoistThenElseCodeToIf(BranchInst *BI, // terminator. Let the loop below handle those 2 cases. } - do { + // Count how many instructions were not hoisted so far. There's a limit on how + // many instructions we skip, serving as a compilation time control as well as + // preventing excessive increase of life ranges. + unsigned NumSkipped = 0; + + // Record if any non-hoisted instruction contains side-effects, as it could + // make it illegal to reorder some instructions across. + bool ForceNoReadMemOrSideEffectsBB1 = false; + bool ForceNoReadMemOrSideEffectsBB2 = false; + + // Record if any non-hoisted instructions does not necessarily transfer + // control to the next instruction. Then we can hoist only instrucions which + // are safe to speculate. + bool ForceNoSpeculationBB1 = false; + bool ForceNoSpeculationBB2 = false; + + for (;;) { // If we are hoisting the terminator instruction, don't move one (making a // broken BB), instead clone it, and remove BI. - if (I1->isTerminator()) + if (I1->isTerminator() || I2->isTerminator()) { + // If any instructions remain in the block, we cannot hoist terminators. + if (NumSkipped || !I1->isIdenticalToWhenDefined(I2)) + return Changed; goto HoistTerminator; + } - // If we're going to hoist a call, make sure that the two instructions we're - // commoning/hoisting are both marked with musttail, or neither of them is - // marked as such. Otherwise, we might end up in a situation where we hoist - // from a block where the terminator is a `ret` to a block where the terminator - // is a `br`, and `musttail` calls expect to be followed by a return. - auto *C1 = dyn_cast(I1); - auto *C2 = dyn_cast(I2); - if (C1 && C2) - if (C1->isMustTailCall() != C2->isMustTailCall()) + if (I1->isIdenticalToWhenDefined(I2)) { + // Hoisting token-returning instructions would obscure the origin. + if (I1->getType()->isTokenTy()) return Changed; - if (!TTI.isProfitableToHoist(I1) || !TTI.isProfitableToHoist(I2)) - return Changed; - - // If any of the two call sites has nomerge attribute, stop hoisting. - if (const auto *CB1 = dyn_cast(I1)) - if (CB1->cannotMerge()) + // Even if the instructions are identical, it may not be safe to hoist + // them if we have skipped over instructions with side effects or their + // operands weren't hoisted. + if (!isSafeToHoistInstr(I1, ForceNoReadMemOrSideEffectsBB1, ForceNoSpeculationBB1) || + !isSafeToHoistInstr(I2, ForceNoReadMemOrSideEffectsBB2, ForceNoSpeculationBB2)) return Changed; - if (const auto *CB2 = dyn_cast(I2)) - if (CB2->cannotMerge()) + + // If we're going to hoist a call, make sure that the two instructions + // we're commoning/hoisting are both marked with musttail, or neither of + // them is marked as such. Otherwise, we might end up in a situation where + // we hoist from a block where the terminator is a `ret` to a block where + // the terminator is a `br`, and `musttail` calls expect to be followed by + // a return. + auto *C1 = dyn_cast(I1); + auto *C2 = dyn_cast(I2); + if (C1 && C2) + if (C1->isMustTailCall() != C2->isMustTailCall()) + return Changed; + + if (!TTI.isProfitableToHoist(I1) || !TTI.isProfitableToHoist(I2)) return Changed; - if (isa(I1) || isa(I2)) { - assert (isa(I1) && isa(I2)); - // The debug location is an integral part of a debug info intrinsic - // and can't be separated from it or replaced. Instead of attempting - // to merge locations, simply hoist both copies of the intrinsic. - BIParent->getInstList().splice(BI->getIterator(), - BB1->getInstList(), I1); - BIParent->getInstList().splice(BI->getIterator(), - BB2->getInstList(), I2); + // If any of the two call sites has nomerge attribute, stop hoisting. + if (const auto *CB1 = dyn_cast(I1)) + if (CB1->cannotMerge()) + return Changed; + if (const auto *CB2 = dyn_cast(I2)) + if (CB2->cannotMerge()) + return Changed; + + if (isa(I1) || isa(I2)) { + assert(isa(I1) && isa(I2)); + // The debug location is an integral part of a debug info intrinsic + // and can't be separated from it or replaced. Instead of attempting + // to merge locations, simply hoist both copies of the intrinsic. + BIParent->getInstList().splice(BI->getIterator(), BB1->getInstList(), + I1); + BIParent->getInstList().splice(BI->getIterator(), BB2->getInstList(), + I2); + } else { + // For a normal instruction, we just move one to right before the + // branch, then replace all uses of the other with the first. Finally, + // we remove the now redundant second instruction. + BIParent->getInstList().splice(BI->getIterator(), BB1->getInstList(), + I1); + if (!I2->use_empty()) + I2->replaceAllUsesWith(I1); + I1->andIRFlags(I2); + unsigned KnownIDs[] = {LLVMContext::MD_tbaa, + LLVMContext::MD_range, + LLVMContext::MD_fpmath, + LLVMContext::MD_invariant_load, + LLVMContext::MD_nonnull, + LLVMContext::MD_invariant_group, + LLVMContext::MD_align, + LLVMContext::MD_dereferenceable, + LLVMContext::MD_dereferenceable_or_null, + LLVMContext::MD_mem_parallel_loop_access, + LLVMContext::MD_access_group, + LLVMContext::MD_preserve_access_index}; + combineMetadata(I1, I2, KnownIDs, true); + + // I1 and I2 are being combined into a single instruction. Its debug + // location is the merged locations of the original instructions. + I1->applyMergedLocation(I1->getDebugLoc(), I2->getDebugLoc()); + + I2->eraseFromParent(); + } Changed = true; + ++NumHoistCommonInstrs; } else { - // For a normal instruction, we just move one to right before the branch, - // then replace all uses of the other with the first. Finally, we remove - // the now redundant second instruction. - BIParent->getInstList().splice(BI->getIterator(), - BB1->getInstList(), I1); - if (!I2->use_empty()) - I2->replaceAllUsesWith(I1); - I1->andIRFlags(I2); - unsigned KnownIDs[] = {LLVMContext::MD_tbaa, - LLVMContext::MD_range, - LLVMContext::MD_fpmath, - LLVMContext::MD_invariant_load, - LLVMContext::MD_nonnull, - LLVMContext::MD_invariant_group, - LLVMContext::MD_align, - LLVMContext::MD_dereferenceable, - LLVMContext::MD_dereferenceable_or_null, - LLVMContext::MD_mem_parallel_loop_access, - LLVMContext::MD_access_group, - LLVMContext::MD_preserve_access_index}; - combineMetadata(I1, I2, KnownIDs, true); - - // I1 and I2 are being combined into a single instruction. Its debug - // location is the merged locations of the original instructions. - I1->applyMergedLocation(I1->getDebugLoc(), I2->getDebugLoc()); - - I2->eraseFromParent(); - Changed = true; + if (NumSkipped >= HoistCommonSkipLimit) + return Changed; + // We are about to skip over a pair of non-identical instructions. Record + // if any of them has side effects. + if (I1->mayHaveSideEffects()) + ForceNoReadMemOrSideEffectsBB1 = true; + if (I2->mayHaveSideEffects()) + ForceNoReadMemOrSideEffectsBB2 = true; + if (!isGuaranteedToTransferExecutionToSuccessor(I1)) + ForceNoSpeculationBB1 = true; + if (!isGuaranteedToTransferExecutionToSuccessor(I2)) + ForceNoSpeculationBB2 = true; + ++NumSkipped; } - ++NumHoistCommonInstrs; I1 = &*BB1_Itr++; I2 = &*BB2_Itr++; @@ -1574,9 +1654,9 @@ bool SimplifyCFGOpt::HoistThenElseCodeToIf(BranchInst *BI, while (isa(I2)) I2 = &*BB2_Itr++; } - } while (I1->isIdenticalToWhenDefined(I2)); + } - return true; + return Changed; HoistTerminator: // It may not be possible to hoist an invoke. diff --git a/llvm/test/Transforms/SimplifyCFG/hoist-common-skip-limit.ll b/llvm/test/Transforms/SimplifyCFG/hoist-common-skip-limit.ll new file mode 100644 index 000000000000..0e1a171dd9eb --- /dev/null +++ b/llvm/test/Transforms/SimplifyCFG/hoist-common-skip-limit.ll @@ -0,0 +1,97 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt -S --passes='simplifycfg' -simplifycfg-hoist-common-skip-limit=0 %s | FileCheck %s --check-prefix=LIMIT0 +; RUN: opt -S --passes='simplifycfg' -simplifycfg-hoist-common-skip-limit=1 %s | FileCheck %s --check-prefix=LIMIT1 +; RUN: opt -S --passes='simplifycfg' -simplifycfg-hoist-common-skip-limit=2 %s | FileCheck %s --check-prefix=LIMIT2 + +define void @f(i1 %c, ptr nocapture noundef %d, ptr nocapture noundef readonly %m, ptr nocapture noundef readonly %b) { +; LIMIT0-LABEL: @f( +; LIMIT0-NEXT: entry: +; LIMIT0-NEXT: [[TMP0:%.*]] = load i16, ptr [[B:%.*]], align 2 +; LIMIT0-NEXT: br i1 [[C:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] +; LIMIT0: if.then: +; LIMIT0-NEXT: call void @no_side_effects0() +; LIMIT0-NEXT: [[ADD:%.*]] = add nsw i16 [[TMP0]], 1 +; LIMIT0-NEXT: [[TMP1:%.*]] = load i16, ptr [[M:%.*]], align 2 +; LIMIT0-NEXT: [[U:%.*]] = add i16 [[ADD]], [[TMP1]] +; LIMIT0-NEXT: br label [[IF_END:%.*]] +; LIMIT0: if.else: +; LIMIT0-NEXT: call void @no_side_effects1() +; LIMIT0-NEXT: [[SUB:%.*]] = sub nsw i16 [[TMP0]], 1 +; LIMIT0-NEXT: [[TMP2:%.*]] = load i16, ptr [[M]], align 2 +; LIMIT0-NEXT: [[V:%.*]] = add i16 [[SUB]], [[TMP2]] +; LIMIT0-NEXT: br label [[IF_END]] +; LIMIT0: if.end: +; LIMIT0-NEXT: [[UV:%.*]] = phi i16 [ [[V]], [[IF_ELSE]] ], [ [[U]], [[IF_THEN]] ] +; LIMIT0-NEXT: store i16 [[UV]], ptr [[D:%.*]], align 2 +; LIMIT0-NEXT: ret void +; +; LIMIT1-LABEL: @f( +; LIMIT1-NEXT: entry: +; LIMIT1-NEXT: [[TMP0:%.*]] = load i16, ptr [[B:%.*]], align 2 +; LIMIT1-NEXT: br i1 [[C:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] +; LIMIT1: if.then: +; LIMIT1-NEXT: call void @no_side_effects0() +; LIMIT1-NEXT: [[ADD:%.*]] = add nsw i16 [[TMP0]], 1 +; LIMIT1-NEXT: [[TMP1:%.*]] = load i16, ptr [[M:%.*]], align 2 +; LIMIT1-NEXT: [[U:%.*]] = add i16 [[ADD]], [[TMP1]] +; LIMIT1-NEXT: br label [[IF_END:%.*]] +; LIMIT1: if.else: +; LIMIT1-NEXT: call void @no_side_effects1() +; LIMIT1-NEXT: [[SUB:%.*]] = sub nsw i16 [[TMP0]], 1 +; LIMIT1-NEXT: [[TMP2:%.*]] = load i16, ptr [[M]], align 2 +; LIMIT1-NEXT: [[V:%.*]] = add i16 [[SUB]], [[TMP2]] +; LIMIT1-NEXT: br label [[IF_END]] +; LIMIT1: if.end: +; LIMIT1-NEXT: [[UV:%.*]] = phi i16 [ [[V]], [[IF_ELSE]] ], [ [[U]], [[IF_THEN]] ] +; LIMIT1-NEXT: store i16 [[UV]], ptr [[D:%.*]], align 2 +; LIMIT1-NEXT: ret void +; +; LIMIT2-LABEL: @f( +; LIMIT2-NEXT: entry: +; LIMIT2-NEXT: [[TMP0:%.*]] = load i16, ptr [[B:%.*]], align 2 +; LIMIT2-NEXT: [[TMP1:%.*]] = load i16, ptr [[M:%.*]], align 2 +; LIMIT2-NEXT: br i1 [[C:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] +; LIMIT2: if.then: +; LIMIT2-NEXT: call void @no_side_effects0() +; LIMIT2-NEXT: [[ADD:%.*]] = add nsw i16 [[TMP0]], 1 +; LIMIT2-NEXT: [[U:%.*]] = add i16 [[ADD]], [[TMP1]] +; LIMIT2-NEXT: br label [[IF_END:%.*]] +; LIMIT2: if.else: +; LIMIT2-NEXT: call void @no_side_effects1() +; LIMIT2-NEXT: [[SUB:%.*]] = sub nsw i16 [[TMP0]], 1 +; LIMIT2-NEXT: [[V:%.*]] = add i16 [[SUB]], [[TMP1]] +; LIMIT2-NEXT: br label [[IF_END]] +; LIMIT2: if.end: +; LIMIT2-NEXT: [[UV:%.*]] = phi i16 [ [[V]], [[IF_ELSE]] ], [ [[U]], [[IF_THEN]] ] +; LIMIT2-NEXT: store i16 [[UV]], ptr [[D:%.*]], align 2 +; LIMIT2-NEXT: ret void +; +entry: + br i1 %c, label %if.then, label %if.else + +if.then: + %0 = load i16, ptr %b, align 2 + call void @no_side_effects0() + %add = add nsw i16 %0, 1 + %1 = load i16, ptr %m, align 2 + %u = add i16 %add, %1 + br label %if.end + +if.else: + %2 = load i16, ptr %b, align 2 + call void @no_side_effects1() + %sub = sub nsw i16 %2, 1 + %3 = load i16, ptr %m, align 2 + %v = add i16 %sub, %3 + br label %if.end + +if.end: + %uv = phi i16 [ %v, %if.else ], [ %u, %if.then ] + store i16 %uv, ptr %d, align 2 + ret void +} + +declare void @side_effects0() +declare void @side_effects1() +declare void @no_side_effects0() readonly nounwind willreturn +declare void @no_side_effects1() readonly nounwind willreturn diff --git a/llvm/test/Transforms/SimplifyCFG/hoist-common-skip.ll b/llvm/test/Transforms/SimplifyCFG/hoist-common-skip.ll new file mode 100644 index 000000000000..400f981cf552 --- /dev/null +++ b/llvm/test/Transforms/SimplifyCFG/hoist-common-skip.ll @@ -0,0 +1,277 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt -S --passes='simplifycfg' %s | FileCheck %s + +;; Check that the two loads are hoisted to the common predecessor, skipping +;; over the add/sub instructions. + +define void @f0(i1 %c, ptr nocapture noundef %d, ptr nocapture noundef readonly %m, ptr nocapture noundef readonly %b) { +; CHECK-LABEL: @f0( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[TMP0:%.*]] = load i16, ptr [[B:%.*]], align 2 +; CHECK-NEXT: [[TMP1:%.*]] = load i16, ptr [[M:%.*]], align 2 +; CHECK-NEXT: br i1 [[C:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] +; CHECK: if.then: +; CHECK-NEXT: [[ADD:%.*]] = add nsw i16 [[TMP0]], 1 +; CHECK-NEXT: [[U:%.*]] = add i16 [[ADD]], [[TMP1]] +; CHECK-NEXT: br label [[IF_END:%.*]] +; CHECK: if.else: +; CHECK-NEXT: [[SUB:%.*]] = sub nsw i16 [[TMP0]], 1 +; CHECK-NEXT: [[TMP2:%.*]] = add i16 [[SUB]], 3 +; CHECK-NEXT: [[V:%.*]] = add i16 [[SUB]], [[TMP2]] +; CHECK-NEXT: br label [[IF_END]] +; CHECK: if.end: +; CHECK-NEXT: [[UV:%.*]] = phi i16 [ [[V]], [[IF_ELSE]] ], [ [[U]], [[IF_THEN]] ] +; CHECK-NEXT: store i16 [[UV]], ptr [[D:%.*]], align 2 +; CHECK-NEXT: ret void +; +entry: + br i1 %c, label %if.then, label %if.else + +if.then: + %0 = load i16, ptr %b, align 2 + %add = add nsw i16 %0, 1 + %1 = load i16, ptr %m, align 2 + %u = add i16 %add, %1 + br label %if.end + +if.else: + %2 = load i16, ptr %b, align 2 + %sub = sub nsw i16 %2, 1 + %3 = load i16, ptr %m, align 2 + %4 = add i16 %sub, 3 + %v = add i16 %sub, %4 + br label %if.end + +if.end: + %uv = phi i16 [ %v, %if.else ], [ %u, %if.then ] + store i16 %uv, ptr %d, align 2 + ret void +} + + +;; Check some instructions (e.g. add) can be reordered across instructions with side +;; effects, while others (e.g. load) can't. +define void @f2(i1 %c, ptr nocapture noundef %d, ptr nocapture noundef readonly %m, ptr nocapture noundef readonly %b) { +; CHECK-LABEL: @f2( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[TMP0:%.*]] = load i16, ptr [[B:%.*]], align 2 +; CHECK-NEXT: [[ADD_0:%.*]] = add nsw i16 [[TMP0]], 1 +; CHECK-NEXT: br i1 [[C:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] +; CHECK: if.then: +; CHECK-NEXT: call void @side_effects0() +; CHECK-NEXT: [[TMP1:%.*]] = load i16, ptr [[M:%.*]], align 2 +; CHECK-NEXT: [[U:%.*]] = add i16 [[ADD_0]], [[TMP1]] +; CHECK-NEXT: br label [[IF_END:%.*]] +; CHECK: if.else: +; CHECK-NEXT: call void @no_side_effects0() +; CHECK-NEXT: [[TMP2:%.*]] = load i16, ptr [[M]], align 2 +; CHECK-NEXT: [[V:%.*]] = add i16 [[ADD_0]], [[TMP2]] +; CHECK-NEXT: br label [[IF_END]] +; CHECK: if.end: +; CHECK-NEXT: [[UV:%.*]] = phi i16 [ [[V]], [[IF_ELSE]] ], [ [[U]], [[IF_THEN]] ] +; CHECK-NEXT: store i16 [[UV]], ptr [[D:%.*]], align 2 +; CHECK-NEXT: ret void +; +entry: + br i1 %c, label %if.then, label %if.else + +if.then: + %0 = load i16, ptr %b, align 2 + call void @side_effects0() + %add.0 = add nsw i16 %0, 1 + %1 = load i16, ptr %m, align 2 + %u = add i16 %add.0, %1 + br label %if.end + +if.else: + %2 = load i16, ptr %b, align 2 + call void @no_side_effects0() + %add.1 = add nsw i16 %2, 1 + %3 = load i16, ptr %m, align 2 + %v = add i16 %add.1, %3 + br label %if.end + +if.end: + %uv = phi i16 [ %v, %if.else ], [ %u, %if.then ] + store i16 %uv, ptr %d, align 2 + ret void +} + + +;; Check indeed it was the side effects that prevented hoisting the load +;; in the previous test. +define void @f3(i1 %c, ptr nocapture noundef %d, ptr nocapture noundef readonly %m, ptr nocapture noundef readonly %b) { +; CHECK-LABEL: @f3( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[TMP0:%.*]] = load i16, ptr [[B:%.*]], align 2 +; CHECK-NEXT: [[ADD_0:%.*]] = add nsw i16 [[TMP0]], 1 +; CHECK-NEXT: [[TMP1:%.*]] = load i16, ptr [[M:%.*]], align 2 +; CHECK-NEXT: [[U:%.*]] = add i16 [[ADD_0]], [[TMP1]] +; CHECK-NEXT: br i1 [[C:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] +; CHECK: if.then: +; CHECK-NEXT: call void @no_side_effects0() +; CHECK-NEXT: br label [[IF_END:%.*]] +; CHECK: if.else: +; CHECK-NEXT: call void @no_side_effects1() +; CHECK-NEXT: br label [[IF_END]] +; CHECK: if.end: +; CHECK-NEXT: store i16 [[U]], ptr [[D:%.*]], align 2 +; CHECK-NEXT: ret void +; +entry: + br i1 %c, label %if.then, label %if.else + +if.then: + %0 = load i16, ptr %b, align 2 + call void @no_side_effects0() + %add.0 = add nsw i16 %0, 1 + %1 = load i16, ptr %m, align 2 + %u = add i16 %add.0, %1 + br label %if.end + +if.else: + %2 = load i16, ptr %b, align 2 + call void @no_side_effects1() + %add.1 = add nsw i16 %2, 1 + %3 = load i16, ptr %m, align 2 + %v = add i16 %add.1, %3 + br label %if.end + +if.end: + %uv = phi i16 [ %v, %if.else ], [ %u, %if.then ] + store i16 %uv, ptr %d, align 2 + ret void +} + +;; Check some instructions (e.g. sdiv) are not speculatively executed. + +;; Division by non-zero constant OK to speculate ... +define void @f4(i1 %c, ptr nocapture noundef %d, ptr nocapture noundef readonly %m, ptr nocapture noundef readonly %b) { +; CHECK-LABEL: @f4( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[TMP0:%.*]] = load i16, ptr [[B:%.*]], align 2 +; CHECK-NEXT: [[DIV_0:%.*]] = sdiv i16 [[TMP0]], 2 +; CHECK-NEXT: [[U:%.*]] = add i16 [[DIV_0]], [[TMP0]] +; CHECK-NEXT: br i1 [[C:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] +; CHECK: if.then: +; CHECK-NEXT: call void @side_effects0() +; CHECK-NEXT: br label [[IF_END:%.*]] +; CHECK: if.else: +; CHECK-NEXT: call void @side_effects1() +; CHECK-NEXT: br label [[IF_END]] +; CHECK: if.end: +; CHECK-NEXT: store i16 [[U]], ptr [[D:%.*]], align 2 +; CHECK-NEXT: ret void +; +entry: + br i1 %c, label %if.then, label %if.else + +if.then: + %0 = load i16, ptr %b, align 2 + call void @side_effects0() + %div.0 = sdiv i16 %0, 2 + %u = add i16 %div.0, %0 + br label %if.end + +if.else: + %1 = load i16, ptr %b, align 2 + call void @side_effects1() + %div.1 = sdiv i16 %1, 2 + %v = add i16 %div.1, %1 + br label %if.end + +if.end: + %uv = phi i16 [ %v, %if.else ], [ %u, %if.then ] + store i16 %uv, ptr %d, align 2 + ret void +} + +;; ... but not a general division ... +define void @f5(i1 %c, ptr nocapture noundef %d, ptr nocapture noundef readonly %m, ptr nocapture noundef readonly %b) { +; CHECK-LABEL: @f5( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[TMP0:%.*]] = load i16, ptr [[B:%.*]], align 2 +; CHECK-NEXT: br i1 [[C:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] +; CHECK: if.then: +; CHECK-NEXT: call void @side_effects0() +; CHECK-NEXT: [[DIV_0:%.*]] = sdiv i16 211, [[TMP0]] +; CHECK-NEXT: [[U:%.*]] = add i16 [[DIV_0]], [[TMP0]] +; CHECK-NEXT: br label [[IF_END:%.*]] +; CHECK: if.else: +; CHECK-NEXT: call void @side_effects1() +; CHECK-NEXT: [[DIV_1:%.*]] = sdiv i16 211, [[TMP0]] +; CHECK-NEXT: [[V:%.*]] = add i16 [[DIV_1]], [[TMP0]] +; CHECK-NEXT: br label [[IF_END]] +; CHECK: if.end: +; CHECK-NEXT: [[UV:%.*]] = phi i16 [ [[V]], [[IF_ELSE]] ], [ [[U]], [[IF_THEN]] ] +; CHECK-NEXT: store i16 [[UV]], ptr [[D:%.*]], align 2 +; CHECK-NEXT: ret void +; +entry: + br i1 %c, label %if.then, label %if.else + +if.then: + %0 = load i16, ptr %b, align 2 + call void @side_effects0() + %div.0 = sdiv i16 211, %0 + %u = add i16 %div.0, %0 + br label %if.end + +if.else: + %1 = load i16, ptr %b, align 2 + call void @side_effects1() + %div.1 = sdiv i16 211, %1 + %v = add i16 %div.1, %1 + br label %if.end + +if.end: + %uv = phi i16 [ %v, %if.else ], [ %u, %if.then ] + store i16 %uv, ptr %d, align 2 + ret void +} + +;; ... and it's also OK to hoist the division when there's no speculation happening. +define void @f6(i1 %c, ptr nocapture noundef %d, ptr nocapture noundef readonly %m, ptr nocapture noundef readonly %b) { +; CHECK-LABEL: @f6( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[TMP0:%.*]] = load i16, ptr [[B:%.*]], align 2 +; CHECK-NEXT: [[DIV_0:%.*]] = sdiv i16 211, [[TMP0]] +; CHECK-NEXT: [[U:%.*]] = add i16 [[DIV_0]], [[TMP0]] +; CHECK-NEXT: br i1 [[C:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] +; CHECK: if.then: +; CHECK-NEXT: call void @no_side_effects0() +; CHECK-NEXT: br label [[IF_END:%.*]] +; CHECK: if.else: +; CHECK-NEXT: call void @no_side_effects1() +; CHECK-NEXT: br label [[IF_END]] +; CHECK: if.end: +; CHECK-NEXT: store i16 [[U]], ptr [[D:%.*]], align 2 +; CHECK-NEXT: ret void +; +entry: + br i1 %c, label %if.then, label %if.else + +if.then: + %0 = load i16, ptr %b, align 2 + call void @no_side_effects0() + %div.0 = sdiv i16 211, %0 + %u = add i16 %div.0, %0 + br label %if.end + +if.else: + %1 = load i16, ptr %b, align 2 + call void @no_side_effects1() + %div.1 = sdiv i16 211, %1 + %v = add i16 %div.1, %1 + br label %if.end + +if.end: + %uv = phi i16 [ %v, %if.else ], [ %u, %if.then ] + store i16 %uv, ptr %d, align 2 + ret void +} + +declare void @side_effects0() +declare void @side_effects1() +declare void @no_side_effects0() readonly nounwind willreturn +declare void @no_side_effects1() readonly nounwind willreturn -- Gitee From e91f13af093e24157a72e202330eb26a6192f67d Mon Sep 17 00:00:00 2001 From: Bryan Chan Date: Tue, 18 Oct 2022 18:24:25 -0400 Subject: [PATCH 02/33] [workflows] Minimal workflow to create an AArch64 container AArch64 GitHub workflows require a Docker container named after the branch. This commit adds the minimal workflow required to create the container image for building and testing subsequent pull requests. --- .github/workflows/Ubuntu20Dockerfile | 65 +++++++++++++++++++ .../build_push_docker_image_Ubuntu20.yml | 49 ++++++++++++++ 2 files changed, 114 insertions(+) create mode 100644 .github/workflows/Ubuntu20Dockerfile create mode 100644 .github/workflows/build_push_docker_image_Ubuntu20.yml diff --git a/.github/workflows/Ubuntu20Dockerfile b/.github/workflows/Ubuntu20Dockerfile new file mode 100644 index 000000000000..fda4dd1f48b4 --- /dev/null +++ b/.github/workflows/Ubuntu20Dockerfile @@ -0,0 +1,65 @@ +FROM ubuntu:20.04 + +ARG DEBIAN_FRONTEND=noninteractive +ENV TZ=Europe/London +RUN apt-get update && \ + apt-get upgrade -y && \ + apt-get install -y \ + curl \ + gcc \ + g++ \ + make \ + htop \ + jq \ + ninja-build \ + tmux \ + git \ + wget \ + patch \ + python3-minimal \ + python-is-python3 \ + libdata-dumper-simple-perl \ + unzip + +RUN apt-get install -y software-properties-common && \ + apt-get update && \ + add-apt-repository ppa:ubuntu-toolchain-r/test && \ + apt-get install -f -y gcc-9 g++-9 && \ + apt-get install -f -y gcc-10 g++-10 && \ + echo 'deb http://apt.llvm.org/focal/ llvm-toolchain-focal-11 main' | tee -a /etc/apt/sources.list.d/llvm.list && \ + echo 'deb-src http://apt.llvm.org/focal/ llvm-toolchain-focal-11 main' | tee -a /etc/apt/sources.list.d/llvm.list && \ + wget -q -O - http://apt.llvm.org/llvm-snapshot.gpg.key | apt-key add - && \ + apt-get update && \ + apt-get install -f -y llvm-9 clang-9 && \ + apt-get install -f -y llvm-10 clang-10 && \ + apt-get install -f -y llvm-11 clang-11 + +# Install the tools for release_13x and newer +RUN apt --fix-missing update && \ + apt install -y build-essential manpages-dev \ + libssl-dev zlib1g-dev \ + libbz2-dev libreadline-dev libsqlite3-dev libncurses5-dev && \ + apt install -y python3-distutils python3-psutil \ + libncursesw5-dev xz-utils tk-dev libffi-dev liblzma-dev python-openssl + +RUN cd /opt && \ + wget https://github.com/Kitware/CMake/releases/download/v3.20.0/cmake-3.20.0-linux-aarch64.sh && \ + /bin/sh cmake-3.20.0-linux-aarch64.sh --skip-license --include-subdir && \ + ln -s /opt/cmake-3.20.0-linux-aarch64/bin/* /usr/local/bin + +RUN ln -s /usr/bin/ninja-build /usr/local/bin/ninja + +RUN mkdir /home/github/ + +ARG BRANCH_NAME +ARG INITIAL_BUILD +RUN if [ "$INITIAL_BUILD" != "true" ]; then \ + mkdir /home/root && cd home/root && \ + git clone --depth 1 --single-branch --branch $BRANCH_NAME https://github.com/flang-compiler/classic-flang-llvm-project.git classic-flang-llvm-project && \ + cd classic-flang-llvm-project && \ + ./build-llvm-project.sh -t AArch64 -p /home/github/usr/local -n `nproc --ignore=1` -a /usr/bin/gcc-10 -b /usr/bin/g++-10 -i -v; \ + fi + +RUN useradd github && \ + chown -R github:github /home/github +USER github diff --git a/.github/workflows/build_push_docker_image_Ubuntu20.yml b/.github/workflows/build_push_docker_image_Ubuntu20.yml new file mode 100644 index 000000000000..f4b7fb3bab44 --- /dev/null +++ b/.github/workflows/build_push_docker_image_Ubuntu20.yml @@ -0,0 +1,49 @@ +name: Pre-compile llvm ARM64 + +on: + workflow_dispatch: + inputs: + initialBuild: + description: "True if creating an initial Docker image for this branch" + required: true + type: boolean + push: + branches: + - 'release_*x' + paths-include: + - '**/.github/workflows/build_push_docker_image_Ubuntu20.yml' + - '**/.github/workflows/Ubuntu20Dockerfile.yml' + +jobs: + docker: + runs-on: self-hosted + steps: + - name: Extract branch name + run: echo "::set-output name=branch::${GITHUB_REF#refs/heads/}" + id: extract_branch + + - name: Checkout + uses: actions/checkout@v2 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v1 + + - name: Log in + uses: docker/login-action@v1 + with: + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Build and push + uses: docker/build-push-action@v2 + with: + file: .github/workflows/Ubuntu20Dockerfile + push: true + no-cache: true + context: .github/workflows + tags: ghcr.io/${{ github.repository_owner }}/ubuntu20-flang-${{ steps.extract_branch.outputs.branch }}:latest + platforms: linux/arm64 + build-args: | + BRANCH_NAME=${{ steps.extract_branch.outputs.branch }} + INITIAL_BUILD=${{ inputs.initialBuild }} -- Gitee From 2923582322e9d0e2c67cfded0dd46f3c75f8f557 Mon Sep 17 00:00:00 2001 From: Eric Schweitz Date: Wed, 21 Aug 2019 13:26:26 -0700 Subject: [PATCH 03/33] Port Classic Flang to LLVM 15 This commit cherry-picks 427c0e83a9f271c3b3f0028201a0c310c7143464 from the release_14x branch, which is a combination of the following legacy patches: Commit 82b38d24a518: [ClassicFlang] Port release_90 changes from flang-compiler/llvm Cherry-picked commit 2085211cfcca70411dc63f0d08763facc8a02090 by Eric Schweitz, resolved merge conflicts, fixed build failures (e.g. adapted CGDebugInfo.cpp to the new API), and fixed the DIGlobalVariable unit tests, which have been broken since commit edfad65eebdf045b050f37380b6b61d673513982. Commit 885dd87e5fdc: [DebugInfo] Removal of DIFortranArrayType and DIFortranSubrange These extensions are no more required after merge of below PR. Commit 5c9b2e0867d5: Modification to incorporate comments from @bryanpkc. Commit 822de2c2a9cc: [AsmPrinter] Fix redundant names and types A bug was introduced in 82b38d24a51871a210a184dd558e9b955a421e8e while cherry-picking a DIGlobalVariable-related patch. Commit 45a70a89626a: Port driver changes from release/11x Cherry-picked c51f89679135f84675f492d560ec5535c2000cfe by Varun Jayathirtha from release_90, and resolved merge conflicts. To avoid conflicts with the new Flang, lib/Driver/ToolChains/Flang.{cpp,h} have been renamed to ClassicFlang.{cpp,h}, and the ENABLE_CLASSIC_FLANG macro is introduced to select which incarnation of Flang to build. The macro is set by running CMake with -DLLVM_ENABLE_CLASSIC_FLANG. After merge with LLVM 11: Move flang options to the end of the definitions list. Commit a9a803645a7d: Port Classic Flang to LLVM 13 File changes to TargetLibraryInfo and DebugLocEntry to adapt to the code from release/13.x and make it work. Comment out the changes due a segmentation fault, code need to be reviewed properly once all commits are in Commit fe989b724392: Fix -fveclib=PGMATH The use of #ifdef in include/clang/Driver/Options.td was incorrect and unsupported. As a result -fveclib=PGMATH was silently ignored, and in LLVM 12, it causes the invocation to fail. This patch unguards the option so that it is parsed correctly, but lets the FLANG_LLVM_EXTENSIONS macro continue to toggle the feature. Commit 7c224ae4708d: Fix use of classic Flang as preprocessor Commit 8403c8335f9a: Merge FLANG_LLVM_EXTENSIONS macro into ENABLE_CLASSIC_FLANG Commit 486741e2e30f: Fix test failures when in classic Flang mode Add a new lit feature tag "classic_flang" to select which tests can or cannot be run when the driver is built for classic Flang. Handle LLVM_ENABLE_CLASSIC_FLANG in llvm/cmake/modules/HandleLLVMOptions.cmake instead of clang/CMakeLists.txt so that macro works in both clang and llvm. Commit a10f592d3b02: Port Classic Flang to LLVM 13 LLVM port from release_12x to release_13x, changes done in order to make project able to be build. Commit d3853218de1a (partial): Change to Options.td in order to add the correct invocation for ffixed_line_length_VALUE. This commit also includes the following legacy patch: Commit 5da2c11605e0: Add DebugInfo tests Commit c379c8d515c0: [ClassicFlang][Driver] Correct the LLVM version passed by the Driver --- clang/CMakeLists.txt | 5 + clang/include/clang/Basic/CodeGenOptions.h | 1 + .../clang/Basic/DiagnosticDriverKinds.td | 6 + clang/include/clang/Basic/MacroBuilder.h | 3 +- clang/include/clang/Basic/Sanitizers.def | 2 + clang/include/clang/Driver/Action.h | 11 + clang/include/clang/Driver/Options.td | 199 ++- clang/include/clang/Driver/Phases.h | 1 + clang/include/clang/Driver/ToolChain.h | 15 + clang/include/clang/Driver/Types.def | 7 + clang/include/clang/Driver/Types.h | 8 + clang/include/clang/Frontend/Utils.h | 31 + clang/lib/CodeGen/BackendUtil.cpp | 5 + clang/lib/CodeGen/CGDebugInfo.cpp | 10 +- clang/lib/Driver/Action.cpp | 7 + clang/lib/Driver/CMakeLists.txt | 5 + clang/lib/Driver/Driver.cpp | 41 + clang/lib/Driver/Phases.cpp | 1 + clang/lib/Driver/ToolChain.cpp | 57 +- clang/lib/Driver/ToolChains/Clang.cpp | 61 + clang/lib/Driver/ToolChains/ClassicFlang.cpp | 1064 +++++++++++++++++ clang/lib/Driver/ToolChains/ClassicFlang.h | 49 + clang/lib/Driver/ToolChains/CommonArgs.cpp | 35 + clang/lib/Driver/ToolChains/CommonArgs.h | 2 + clang/lib/Driver/ToolChains/Cuda.cpp | 33 + clang/lib/Driver/ToolChains/Cuda.h | 3 + clang/lib/Driver/ToolChains/Gnu.cpp | 10 + clang/lib/Driver/ToolChains/Linux.cpp | 188 +++ clang/lib/Driver/ToolChains/Linux.h | 3 + clang/lib/Driver/Types.cpp | 49 + clang/lib/Frontend/InitPreprocessor.cpp | 20 - clang/test/Driver/autocomplete.c | 2 +- clang/test/Driver/flang/classic_flang.f95 | 28 + clang/test/Driver/flang/flang.f90 | 2 + clang/test/Driver/flang/flang_ucase.F90 | 2 + .../Driver/flang/multiple-inputs-mixed.f90 | 2 + clang/test/Driver/flang/multiple-inputs.f90 | 2 + clang/test/Driver/fortran.f95 | 2 + clang/test/Driver/gfortran.f90 | 1 + clang/test/lit.cfg.py | 3 + clang/test/lit.site.cfg.py.in | 1 + .../ClangOffloadBundler.cpp | 2 + clang/tools/driver/CMakeLists.txt | 2 +- llvm/cmake/modules/HandleLLVMOptions.cmake | 8 + llvm/include/llvm-c/DebugInfo.h | 5 +- .../include/llvm/Analysis/TargetLibraryInfo.h | 1 + llvm/include/llvm/IR/DIBuilder.h | 19 +- llvm/include/llvm/IR/DebugInfoMetadata.h | 32 +- llvm/lib/Analysis/TargetLibraryInfo.cpp | 454 ++++++- llvm/lib/AsmParser/LLParser.cpp | 22 +- llvm/lib/Bitcode/Reader/MetadataLoader.cpp | 42 +- llvm/lib/Bitcode/Writer/BitcodeWriter.cpp | 3 +- llvm/lib/CodeGen/AsmPrinter/DebugLocEntry.h | 89 ++ .../lib/CodeGen/AsmPrinter/DebugLocStream.cpp | 5 +- llvm/lib/CodeGen/AsmPrinter/DebugLocStream.h | 7 +- .../CodeGen/AsmPrinter/DwarfCompileUnit.cpp | 3 + .../lib/CodeGen/AsmPrinter/DwarfCompileUnit.h | 8 + llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp | 76 ++ llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h | 12 + llvm/lib/IR/AsmWriter.cpp | 1 + llvm/lib/IR/DIBuilder.cpp | 12 +- llvm/lib/IR/DebugInfo.cpp | 10 +- llvm/lib/IR/DebugInfoMetadata.cpp | 12 +- llvm/lib/IR/LLVMContextImpl.h | 11 +- .../Instrumentation/InstrProfiling.cpp | 4 +- .../Transforms/Vectorize/LoopVectorize.cpp | 6 +- .../invalid-diglobalvariable-empty-name.ll | 1 + .../Generic/fortran-subprogram-at.ll | 24 + .../DebugInfo/Generic/more-subprogram-attr.ll | 38 + llvm/test/DebugInfo/X86/DICommonBlock.ll | 36 + llvm/test/lit.cfg.py | 3 + llvm/test/lit.site.cfg.py.in | 1 + llvm/tools/llvm-c-test/debuginfo.c | 4 +- llvm/unittests/IR/MetadataTest.cpp | 47 +- 74 files changed, 2853 insertions(+), 124 deletions(-) create mode 100644 clang/lib/Driver/ToolChains/ClassicFlang.cpp create mode 100644 clang/lib/Driver/ToolChains/ClassicFlang.h mode change 100644 => 100755 clang/lib/Driver/Types.cpp create mode 100644 clang/test/Driver/flang/classic_flang.f95 create mode 100644 llvm/test/DebugInfo/Generic/fortran-subprogram-at.ll create mode 100644 llvm/test/DebugInfo/Generic/more-subprogram-attr.ll create mode 100644 llvm/test/DebugInfo/X86/DICommonBlock.ll diff --git a/clang/CMakeLists.txt b/clang/CMakeLists.txt index e3bc4b468fb6..4c100422f9dc 100644 --- a/clang/CMakeLists.txt +++ b/clang/CMakeLists.txt @@ -491,6 +491,11 @@ endif() add_definitions( -D_GNU_SOURCE ) +option(LLVM_ENABLE_CLASSIC_FLANG "Build support for classic Flang instead of the new built-in Flang" OFF) +if(LLVM_ENABLE_CLASSIC_FLANG) + add_definitions( -DENABLE_CLASSIC_FLANG ) +endif() + option(CLANG_BUILD_TOOLS "Build the Clang tools. If OFF, just generate build targets." ON) diff --git a/clang/include/clang/Basic/CodeGenOptions.h b/clang/include/clang/Basic/CodeGenOptions.h index cd204e5d7c15..fe320acc9caf 100644 --- a/clang/include/clang/Basic/CodeGenOptions.h +++ b/clang/include/clang/Basic/CodeGenOptions.h @@ -59,6 +59,7 @@ public: Accelerate, // Use the Accelerate framework. LIBMVEC, // GLIBC vector math library. MASSV, // IBM MASS vector library. + PGMATH, // PGI math library. SVML, // Intel short vector math library. Darwin_libsystem_m // Use Darwin's libsytem_m vector functions. }; diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td index 2f600d28fea0..fb78977b2699 100644 --- a/clang/include/clang/Basic/DiagnosticDriverKinds.td +++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td @@ -117,6 +117,10 @@ def err_drv_invalid_linker_name : Error< "invalid linker name in argument '%0'">; def err_drv_invalid_rtlib_name : Error< "invalid runtime library name in argument '%0'">; +def err_drv_invalid_allocatable_mode : Error< + "invalid semantic mode for assignments to allocatables in argument '%0'">; +def err_drv_unsupported_fixed_line_length : Error< + "unsupported fixed-format line length in argument '%0'">; def err_drv_unsupported_rtlib_for_platform : Error< "unsupported runtime library '%0' for platform '%1'">; def err_drv_invalid_unwindlib_name : Error< @@ -335,6 +339,8 @@ def err_drv_negative_columns : Error< "invalid value '%1' in '%0', value must be 'none' or a positive integer">; def err_drv_small_columns : Error< "invalid value '%1' in '%0', value must be '%2' or greater">; +def err_drv_clang_unsupported_minfo_arg : Error< + "'%0' option does not support '%1' value">; def err_drv_invalid_malign_branch_EQ : Error< "invalid argument '%0' to -malign-branch=; each element must be one of: %1">; diff --git a/clang/include/clang/Basic/MacroBuilder.h b/clang/include/clang/Basic/MacroBuilder.h index 96e67cbbfa3f..bfc5e38c15e3 100644 --- a/clang/include/clang/Basic/MacroBuilder.h +++ b/clang/include/clang/Basic/MacroBuilder.h @@ -24,9 +24,10 @@ class MacroBuilder { raw_ostream &Out; public: MacroBuilder(raw_ostream &Output) : Out(Output) {} + virtual ~MacroBuilder() {} /// Append a \#define line for macro of the form "\#define Name Value\n". - void defineMacro(const Twine &Name, const Twine &Value = "1") { + virtual void defineMacro(const Twine &Name, const Twine &Value = "1") { Out << "#define " << Name << ' ' << Value << '\n'; } diff --git a/clang/include/clang/Basic/Sanitizers.def b/clang/include/clang/Basic/Sanitizers.def index 8e7b6cd0a7e2..24dc2b668404 100644 --- a/clang/include/clang/Basic/Sanitizers.def +++ b/clang/include/clang/Basic/Sanitizers.def @@ -107,6 +107,8 @@ SANITIZER("signed-integer-overflow", SignedIntegerOverflow) SANITIZER("unreachable", Unreachable) SANITIZER("vla-bound", VLABound) SANITIZER("vptr", Vptr) +// fortran contiguous pointer checks +SANITIZER("discontiguous", Discontiguous) // IntegerSanitizer SANITIZER("unsigned-integer-overflow", UnsignedIntegerOverflow) diff --git a/clang/include/clang/Driver/Action.h b/clang/include/clang/Driver/Action.h index 684ccd358275..b1a91edb6158 100644 --- a/clang/include/clang/Driver/Action.h +++ b/clang/include/clang/Driver/Action.h @@ -63,6 +63,7 @@ public: AnalyzeJobClass, MigrateJobClass, CompileJobClass, + FortranFrontendJobClass, BackendJobClass, AssembleJobClass, LinkJobClass, @@ -487,6 +488,16 @@ public: } }; +class FortranFrontendJobAction : public JobAction { + void anchor() override; +public: + FortranFrontendJobAction(Action *Input, types::ID OutputType); + + static bool classof(const Action *A) { + return A->getKind() == FortranFrontendJobClass; + } +}; + class CompileJobAction : public JobAction { void anchor() override; diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 3cab37b21aaf..29b328429752 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -533,7 +533,7 @@ class InternalDriverOpt : Group, Flags<[NoXarchOption, HelpHidden]>; def driver_mode : Joined<["--"], "driver-mode=">, Group, Flags<[CoreOption, NoXarchOption, HelpHidden]>, - HelpText<"Set the driver mode to either 'gcc', 'g++', 'cpp', or 'cl'">; + HelpText<"Set the driver mode to either 'gcc', 'g++', 'cpp', 'cl', or 'fortran'">; def rsp_quoting : Joined<["--"], "rsp-quoting=">, Group, Flags<[CoreOption, NoXarchOption, HelpHidden]>, HelpText<"Set the rsp quoting to either 'posix', or 'windows'">; @@ -2397,9 +2397,9 @@ def fno_experimental_isel : Flag<["-"], "fno-experimental-isel">, Group; def fveclib : Joined<["-"], "fveclib=">, Group, Flags<[CC1Option]>, HelpText<"Use the given vector functions library">, - Values<"Accelerate,libmvec,MASSV,SVML,Darwin_libsystem_m,none">, + Values<"Accelerate,libmvec,MASSV,PGMATH,SVML,Darwin_libsystem_m,none">, NormalizedValuesScope<"CodeGenOptions">, - NormalizedValues<["Accelerate", "LIBMVEC", "MASSV", "SVML", + NormalizedValues<["Accelerate", "LIBMVEC", "MASSV", "PGMATH", "SVML", "Darwin_libsystem_m", "NoLibrary"]>, MarshallingInfoEnum, "NoLibrary">; def fno_lax_vector_conversions : Flag<["-"], "fno-lax-vector-conversions">, Group, @@ -4790,6 +4790,12 @@ defm devirtualize : BooleanFFlag<"devirtualize">, Group, Group; +// gfortran options that we recognize in the driver and pass along when +// invoking GCC to compile Fortran code. +def flang_rt_Group : OptionGroup<"Flang runtime library Group">; +def pgi_fortran_Group : OptionGroup<"PGI Fortran compatibility Group">, + Flags<[HelpHidden]>; + // Generic gfortran options. def A_DASH : Joined<["-"], "A-">, Group; def static_libgfortran : Flag<["-"], "static-libgfortran">, Group; @@ -4811,6 +4817,8 @@ def fmax_stack_var_size_EQ : Joined<["-"], "fmax-stack-var-size=">, Group, Group; // "f" flags for gfortran. defm aggressive_function_elimination : BooleanFFlag<"aggressive-function-elimination">, Group; defm align_commons : BooleanFFlag<"align-commons">, Group; @@ -4822,13 +4830,19 @@ defm check_array_temporaries : BooleanFFlag<"check-array-temporaries">, Group, Group; defm d_lines_as_code : BooleanFFlag<"d-lines-as-code">, Group; defm d_lines_as_comments : BooleanFFlag<"d-lines-as-comments">, Group; +def default_integer_8_fno : Flag<["-"], "fno-default-integer-8">, Group; +def default_real_8_fno : Flag<["-"], "fno-default-real-8">, Group; defm dollar_ok : BooleanFFlag<"dollar-ok">, Group; defm dump_fortran_optimized : BooleanFFlag<"dump-fortran-optimized">, Group; defm dump_fortran_original : BooleanFFlag<"dump-fortran-original">, Group; defm dump_parse_tree : BooleanFFlag<"dump-parse-tree">, Group; defm external_blas : BooleanFFlag<"external-blas">, Group; defm f2c : BooleanFFlag<"f2c">, Group; -defm frontend_optimize : BooleanFFlag<"frontend-optimize">, Group; +def fixed_form_off : Flag<["-"], "fno-fixed-form">, Group, + HelpText<"Disable fixed-form format for Fortran">; +def free_form_off : Flag<["-"], "fno-free-form">, Group, + HelpText<"Disable free-form format for Fortran">; +defm frontend_optimize : BooleanFFlag<"frontend-optimize">, Group; defm init_local_zero : BooleanFFlag<"init-local-zero">, Group; defm integer_4_integer_8 : BooleanFFlag<"integer-4-integer-8">, Group; defm max_identifier_length : BooleanFFlag<"max-identifier-length">, Group; @@ -4880,9 +4894,9 @@ def Xflang : Separate<["-"], "Xflang">, let Flags = [FC1Option, FlangOption, FlangOnlyOption] in { -def cpp : Flag<["-"], "cpp">, Group, +def cpp : Flag<["-"], "cpp">, Group, HelpText<"Enable predefined and command line preprocessor macros">; -def nocpp : Flag<["-"], "nocpp">, Group, +def nocpp : Flag<["-"], "nocpp">, Group, HelpText<"Disable predefined and command line preprocessor macros">; def module_dir : JoinedOrSeparate<["-"], "module-dir">, MetaVarName<"">, HelpText<"Put MODULE files in ">, @@ -4890,33 +4904,47 @@ def module_dir : JoinedOrSeparate<["-"], "module-dir">, MetaVarName<"">, It is also added to the list of directories to be searched by an USE statement. The default is the current directory.}]>; -def ffixed_form : Flag<["-"], "ffixed-form">, Group, +def ffixed_form : Flag<["-"], "ffixed-form">, Group, HelpText<"Process source files in fixed form">; -def ffree_form : Flag<["-"], "ffree-form">, Group, +#ifdef ENABLE_CLASSIC_FLANG +def fno_fixed_form : Flag<["-"], "fno-fixed-form">, Group, + HelpText<"Disable fixed-form format for Fortran">; +#endif +def ffree_form : Flag<["-"], "ffree-form">, Group, HelpText<"Process source files in free form">; -def ffixed_line_length_EQ : Joined<["-"], "ffixed-line-length=">, Group, +#ifdef ENABLE_CLASSIC_FLANG +def fno_free_form : Flag<["-"], "fno-free-form">, Group, + HelpText<"Disable free-form format for Fortran">; +#endif +def ffixed_line_length_EQ : Joined<["-"], "ffixed-line-length=">, Group, HelpText<"Use as character line width in fixed mode">, DocBrief<[{Set column after which characters are ignored in typical fixed-form lines in the source file}]>; -def ffixed_line_length_VALUE : Joined<["-"], "ffixed-line-length-">, Group, Alias; +def ffixed_line_length_VALUE : Joined<["-"], "ffixed-line-length-">, Group, + HelpText<"Set line length in fixed-form format Fortran, current supporting only 72 and 132 characters">; def fopenacc : Flag<["-"], "fopenacc">, Group, HelpText<"Enable OpenACC">; -def fdefault_double_8 : Flag<["-"],"fdefault-double-8">, Group, +def fdefault_double_8 : Flag<["-"],"fdefault-double-8">, Group, HelpText<"Set the default double precision kind to an 8 byte wide type">; -def fdefault_integer_8 : Flag<["-"],"fdefault-integer-8">, Group, +def fdefault_integer_8 : Flag<["-"],"fdefault-integer-8">, Group, HelpText<"Set the default integer kind to an 8 byte wide type">; -def fdefault_real_8 : Flag<["-"],"fdefault-real-8">, Group, +def fdefault_real_8 : Flag<["-"],"fdefault-real-8">, Group, HelpText<"Set the default real kind to an 8 byte wide type">; def flarge_sizes : Flag<["-"],"flarge-sizes">, Group, HelpText<"Use INTEGER(KIND=8) for the result type in size-related intrinsics">; - def falternative_parameter_statement : Flag<["-"], "falternative-parameter-statement">, Group, HelpText<"Enable the old style PARAMETER statement">; def fintrinsic_modules_path : Separate<["-"], "fintrinsic-modules-path">, Group, MetaVarName<"">, HelpText<"Specify where to find the compiled intrinsic modules">, DocBrief<[{This option specifies the location of pre-compiled intrinsic modules, if they are not in the default location expected by the compiler.}]>; - +#ifdef ENABLE_CLASSIC_FLANG +def fbackslash : Flag<["-"], "fbackslash">, Group, + HelpText<"Specify that backslash in string introduces an escape character">, + DocBrief<[{Change the interpretation of backslashes in string literals from +a single backslash character to "C-style" escape characters.}]>; +def fno_backslash : Flag<["-"], "fno-backslash">, Group; +#else defm backslash : OptInFC1FFlag<"backslash", "Specify that backslash in string introduces an escape character">; defm xor_operator : OptInFC1FFlag<"xor-operator", "Enable .XOR. as a synonym of .NEQV.">; defm logical_abbreviations : OptInFC1FFlag<"logical-abbreviations", "Enable logical abbreviations">; @@ -4924,13 +4952,19 @@ defm implicit_none : OptInFC1FFlag<"implicit-none", "No implicit typing allowed def fno_automatic : Flag<["-"], "fno-automatic">, Group, HelpText<"Implies the SAVE attribute for non-automatic local objects in subprograms unless RECURSIVE">; - +#endif } // let Flags = [FC1Option, FlangOption, FlangOnlyOption] +#ifdef ENABLE_CLASSIC_FLANG +def J : JoinedOrSeparate<["-"], "J">, + Flags<[RenderJoined]>, + Group; +#else def J : JoinedOrSeparate<["-"], "J">, Flags<[RenderJoined, FlangOption, FC1Option, FlangOnlyOption]>, Group, Alias; +#endif //===----------------------------------------------------------------------===// // FC1 Options @@ -6913,3 +6947,136 @@ def fcgl : DXCFlag<"fcgl">, Alias; def enable_16bit_types : DXCFlag<"enable-16bit-types">, Alias, HelpText<"Enable 16-bit types and disable min precision types." "Available in HLSL 2018 and shader model 6.2.">; + +// Classic Flang-specific options +multiclass BooleanKFlag { + def _on : Flag<["-"], "K"#name>; + def _off : Flag<["-"], "Kno"#name>; +} + +multiclass BooleanMFlag { + def _on : Flag<["-"], "M"#name>; + def _off : Flag<["-"], "Mno"#name>; +} + +def Mfixed : Flag<["-"], "Mfixed">, Group, + HelpText<"Force fixed-form format Fortran">, + Flags<[HelpHidden]>; +def Mfree_on: Flag<["-"], "Mfree">, Group, + HelpText<"Enable free-form format for Fortran">, + Flags<[HelpHidden]>; +def Mfree_off: Flag<["-"], "Mnofree">, Group, + HelpText<"Disable free-form format for Fortran">, + Flags<[HelpHidden]>; +def Mfreeform_on: Flag<["-"], "Mfreeform">, Group, + HelpText<"Enable free-form format for Fortran">, + Flags<[HelpHidden]>; +def Mfreeform_off: Flag<["-"], "Mnofreeform">, Group, + HelpText<"Disable free-form format for Fortran">, + Flags<[HelpHidden]>; + +def Minfo_EQ : CommaJoined<["-"], "Minfo=">, + HelpText<"Diagnostic information about successful optimizations">, + Values<"all,vect,inline">; +def Minfoall : Flag<["-"], "Minfo">, + HelpText<"Diagnostic information about all successful optimizations">; +def Mneginfo_EQ : CommaJoined<["-"], "Mneginfo=">, + HelpText<"Diagnostic information about missed optimizations">, + Values<"all,vect,inline">; +def Mneginfoall : Flag<["-"], "Mneginfo">, + HelpText<"Diagnostic information about all missed optimizations">; + +def Mipa: Joined<["-"], "Mipa">, Group; +def Mstackarrays: Joined<["-"], "Mstack_arrays">, Group; +def pc: JoinedOrSeparate<["-"], "pc">, Group; +def Mfprelaxed: Joined<["-"], "Mfprelaxed">, Group; +def Mnofprelaxed: Joined<["-"], "Mnofprelaxed">, Group; +defm Mstride0: BooleanMFlag<"stride0">, Group; +defm Mrecursive: BooleanMFlag<"recursive">, Group; +defm Mreentrant: BooleanMFlag<"reentrant">, Group; +defm Mbounds: BooleanMFlag<"bounds">, Group; +def Mdaz_on: Flag<["-"], "Mdaz">, Group, + HelpText<"Treat denormalized numbers as zero">; +def Mdaz_off: Flag<["-"], "Mnodaz">, Group, + HelpText<"Disable treating denormalized numbers as zero">; +def Kieee_on : Flag<["-"], "Kieee">, Group, + HelpText<"Enable IEEE division">; +def Kieee_off : Flag<["-"], "Knoieee">, Group, + HelpText<"Disable IEEE division">; +def Mextend : Flag<["-"], "Mextend">, Group, + HelpText<"Allow lines up to 132 characters in Fortran sources">; +def Mpreprocess : Flag<["-"], "Mpreprocess">, Group, + HelpText<"Preprocess Fortran files">; +def Mstandard: Flag<["-"], "Mstandard">, Group, + HelpText<"Check Fortran standard conformance">; +def Mchkptr: Flag<["-"], "Mchkptr">, Group; +def Mwritable_constants: Flag<["-"], "Mwritable-constants">, Group, + HelpText<"Store constants in the writable data segment">; +defm Minline: BooleanMFlag<"inline">, Group; +def fma: Flag<["-"], "fma">, Group, + HelpText<"Enable generation of FMA instructions">; +def nofma: Flag<["-"], "nofma">, Group, + HelpText<"Disable generation of FMA instructions">; +defm Mfma: BooleanMFlag<"fma">, Group, + HelpText<"Enable generation of FMA instructions">; +def mp: Flag<["-"], "mp">, Group, + HelpText<"Enable OpenMP">; +def nomp: Flag<["-"], "nomp">, Group, + HelpText<"Do not link with OpenMP library libomp">; +def Mflushz_on: Flag<["-"], "Mflushz">, Group, + HelpText<"Set SSE to flush-to-zero mode">; +def Mflushz_off: Flag<["-"], "Mnoflushz">, Group, + HelpText<"Disabling setting SSE to flush-to-zero mode">; +def Msave_on: Flag<["-"], "Msave">, Group, + HelpText<"Assume all Fortran variables have SAVE attribute">; +def Msave_off: Flag<["-"], "Mnosave">, Group, + HelpText<"Assume no Fortran variables have SAVE attribute">; +def Mcache_align_on: Flag<["-"], "Mcache_align">, Group, + HelpText<"Align large objects on cache-line boundaries">; +def Mcache_align_off: Flag<["-"], "Mnocache_align">, Group, + HelpText<"Disable aligning large objects on cache-line boundaries">; +def ModuleDir : Separate<["-"], "module">, Group, + HelpText<"Fortran module path">; +def Minform_EQ : Joined<["-"], "Minform=">, + HelpText<"Set error level of messages to display">; +def Mallocatable_EQ : Joined<["-"], "Mallocatable=">, + HelpText<"Select semantics for assignments to allocatables (F03 or F95)">; +def Mbyteswapio: Flag<["-"], "Mbyteswapio">, Group, + HelpText<"Swap byte-order for unformatted input/output">; +def byteswapio: Flag<["-"], "byteswapio">, Group, + HelpText<"Swap byte-order for unformatted input/output">; +def Mbackslash: Flag<["-"], "Mbackslash">, Group, + HelpText<"Treat backslash like any other character in character strings">; +def Mnobackslash: Flag<["-"], "Mnobackslash">, Group, + HelpText<"Treat backslash as C-style escape character">; +def staticFlangLibs: Flag<["-"], "static-flang-libs">, Group, + HelpText<"Link using static Flang libraries">; +def noFlangLibs: Flag<["-"], "no-flang-libs">, Group, + HelpText<"Do not link against Flang libraries">; +def r8: Flag<["-"], "r8">, Group, + HelpText<"Treat REAL as REAL*8">; +def i8: Flag<["-"], "i8">, Group, + HelpText<"Treat INTEGER and LOGICAL as INTEGER*8 and LOGICAL*8">; +def no_fortran_main: Flag<["-"], "fno-fortran-main">, Group, + HelpText<"Don't link in Fortran main">; +def Mnomain: Flag<["-"], "Mnomain">, Group, + HelpText<"Don't link in Fortran main">; +def frelaxed_math : Flag<["-"], "frelaxed-math">, Group, + HelpText<"Use relaxed Math intrinsic functions">; +def Memit_dwarf_common_blocks_name: Flag<["-"], "Memit-dwarf-common-blocks-name">, + Group, HelpText<"Emit COMMON blocks name in DWARF">; +def Munixlogical: Flag<["-"], "Munixlogical">, Group, + HelpText<"Use unixlogical for all loigical operations">; + +// Flang internal debug options +def Mx_EQ : Joined<["-"], "Mx,">, Group; +def My_EQ : Joined<["-"], "My,">, Group; +def Hx_EQ : Joined<["-"], "Hx,">, Group; +def Hy_EQ : Joined<["-"], "Hy,">, Group; +def Wm_EQ : Joined<["-"], "Wm,">, Group; + +def Mq_EQ : Joined<["-"], "Mq,">, Group; +def Hq_EQ : Joined<["-"], "Hq,">, Group; +def Mqq_EQ : Joined<["-"], "Mqq,">, Group; +def Hqq_EQ : Joined<["-"], "Hqq,">, Group; +def Wh_EQ : Joined<["-"], "Wh,">, Group; diff --git a/clang/include/clang/Driver/Phases.h b/clang/include/clang/Driver/Phases.h index 9003c5857351..f8cac9548d02 100644 --- a/clang/include/clang/Driver/Phases.h +++ b/clang/include/clang/Driver/Phases.h @@ -17,6 +17,7 @@ namespace phases { enum ID { Preprocess, Precompile, + FortranFrontend, Compile, Backend, Assemble, diff --git a/clang/include/clang/Driver/ToolChain.h b/clang/include/clang/Driver/ToolChain.h index 53c86ee82936..66cd1823033d 100644 --- a/clang/include/clang/Driver/ToolChain.h +++ b/clang/include/clang/Driver/ToolChain.h @@ -145,6 +145,7 @@ private: mutable std::unique_ptr Clang; mutable std::unique_ptr Flang; + mutable std::unique_ptr FortranFrontend; mutable std::unique_ptr Assemble; mutable std::unique_ptr Link; mutable std::unique_ptr StaticLibTool; @@ -156,6 +157,7 @@ private: Tool *getClang() const; Tool *getFlang() const; + Tool *getFortranFrontend() const; Tool *getAssemble() const; Tool *getLink() const; Tool *getStaticLibTool() const; @@ -621,6 +623,14 @@ public: AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args) const; + /// \brief Add the flang arguments for system include paths. + /// + /// This routine is responsible for adding the -stdinc argument to + /// include headers and module files from standard system header directories. + virtual void + AddFlangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs, + llvm::opt::ArgStringList &Flang1Args) const { } + /// Add options that need to be passed to cc1 for this target. virtual void addClangTargetOptions(const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args, @@ -718,6 +728,11 @@ public: virtual void AddHIPRuntimeLibArgs(const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs) const {} + /// AddFortranStdlibLibArgs - Add the system specific linker arguments to use + /// for the given Fortran runtime library type. + virtual void AddFortranStdlibLibArgs(const llvm::opt::ArgList &Args, + llvm::opt::ArgStringList &CmdArgs) const; + /// Return sanitizers which are available in this toolchain. virtual SanitizerMask getSupportedSanitizers() const; diff --git a/clang/include/clang/Driver/Types.def b/clang/include/clang/Driver/Types.def index d00d520d7514..7f91e348d875 100644 --- a/clang/include/clang/Driver/Types.def +++ b/clang/include/clang/Driver/Types.def @@ -77,8 +77,15 @@ TYPE("c++-module-cpp-output", PP_CXXModule, INVALID, "iim", phases TYPE("ada", Ada, INVALID, nullptr, phases::Compile, phases::Backend, phases::Assemble, phases::Link) TYPE("assembler", PP_Asm, INVALID, "s", phases::Assemble, phases::Link) TYPE("assembler-with-cpp", Asm, PP_Asm, "S", phases::Preprocess, phases::Assemble, phases::Link) +#ifdef ENABLE_CLASSIC_FLANG +TYPE("f77", PP_F_FixedForm, INVALID, "f", phases::FortranFrontend, phases::Backend, phases::Assemble, phases::Link) +TYPE("f77-cpp-input", F_FixedForm, PP_F_FixedForm, "F", phases::FortranFrontend, phases::Backend, phases::Assemble, phases::Link) +TYPE("f95", PP_F_FreeForm, INVALID, "f95", phases::FortranFrontend, phases::Backend, phases::Assemble, phases::Link) +TYPE("f95-cpp-input", F_FreeForm, PP_F_FreeForm, "F95", phases::FortranFrontend, phases::Backend, phases::Assemble, phases::Link) +#else TYPE("f95", PP_Fortran, INVALID, "i", phases::Compile, phases::Backend, phases::Assemble, phases::Link) TYPE("f95-cpp-input", Fortran, PP_Fortran, nullptr, phases::Preprocess, phases::Compile, phases::Backend, phases::Assemble, phases::Link) +#endif TYPE("java", Java, INVALID, nullptr, phases::Compile, phases::Backend, phases::Assemble, phases::Link) // LLVM IR/LTO types. We define separate types for IR and LTO because LTO diff --git a/clang/include/clang/Driver/Types.h b/clang/include/clang/Driver/Types.h index fc5dd7bbfd6f..e8000778076a 100644 --- a/clang/include/clang/Driver/Types.h +++ b/clang/include/clang/Driver/Types.h @@ -95,6 +95,14 @@ namespace types { /// isOpenCL - Is this an "OpenCL" input. bool isOpenCL(ID Id); +#ifdef ENABLE_CLASSIC_FLANG + /// isFreeFormFortran -- is it a free form layout Fortran input + bool isFreeFormFortran(ID Id); + + /// isFixedFormFortran -- is it a fixed form layout Fortran input + bool isFixedFormFortran(ID Id); +#endif + /// isSrcFile - Is this a source file, i.e. something that still has to be /// preprocessed. The logic behind this is the same that decides if the first /// compilation phase is a preprocessing one. diff --git a/clang/include/clang/Frontend/Utils.h b/clang/include/clang/Frontend/Utils.h index 143cf4359f00..f9a7e25c0049 100644 --- a/clang/include/clang/Frontend/Utils.h +++ b/clang/include/clang/Frontend/Utils.h @@ -17,6 +17,7 @@ #include "clang/Basic/LLVM.h" #include "clang/Driver/OptionUtils.h" #include "clang/Frontend/DependencyOutputOptions.h" +#include "clang/Basic/TargetInfo.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/StringMap.h" @@ -31,6 +32,12 @@ #include #include +namespace llvm { + +class StringRef; + +} // namespace llvm + namespace clang { class ASTReader; @@ -39,6 +46,7 @@ class CompilerInvocation; class DiagnosticsEngine; class ExternalSemaSource; class FrontendOptions; +class MacroBuilder; class PCHContainerReader; class Preprocessor; class PreprocessorOptions; @@ -54,6 +62,29 @@ void InitializePreprocessor(Preprocessor &PP, const PreprocessorOptions &PPOpts, void DoPrintPreprocessedInput(Preprocessor &PP, raw_ostream *OS, const PreprocessorOutputOptions &Opts); +/// DefineTypeSize - Emit a macro to the predefines buffer that declares a macro +/// named MacroName with the max value for a type with width 'TypeWidth' a +/// signedness of 'isSigned' and with a value suffix of 'ValSuffix' (e.g. LL). +template +static void DefineTypeSize(const Twine &MacroName, unsigned TypeWidth, + StringRef ValSuffix, bool isSigned, + T &Builder) { + static_assert(std::is_base_of::value, "Illegal T value"); + llvm::APInt MaxVal = isSigned ? llvm::APInt::getSignedMaxValue(TypeWidth) + : llvm::APInt::getMaxValue(TypeWidth); + Builder.defineMacro(MacroName, toString(MaxVal, 10, isSigned) + ValSuffix); +} + +/// DefineTypeSize - An overloaded helper that uses TargetInfo to determine +/// the width, suffix, and signedness of the given type +template +static void DefineTypeSize(const Twine &MacroName, TargetInfo::IntType Ty, + const TargetInfo &TI, T &Builder) { + static_assert(std::is_base_of::value, "Illegal T value"); + DefineTypeSize(MacroName, TI.getTypeWidth(Ty), TI.getTypeConstantSuffix(Ty), + TI.isTypeSigned(Ty), Builder); +} + /// An interface for collecting the dependencies of a compilation. Users should /// use \c attachToPreprocessor and \c attachToASTReader to get all of the /// dependencies. diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp index 7c4e35634e5d..985ef011f301 100644 --- a/clang/lib/CodeGen/BackendUtil.cpp +++ b/clang/lib/CodeGen/BackendUtil.cpp @@ -272,6 +272,11 @@ static TargetLibraryInfoImpl *createTLII(llvm::Triple &TargetTriple, TLII->addVectorizableFunctionsFromVecLib( TargetLibraryInfoImpl::DarwinLibSystemM); break; +#ifdef ENABLE_CLASSIC_FLANG + case CodeGenOptions::PGMATH: + TLII->addVectorizableFunctionsFromVecLib(TargetLibraryInfoImpl::PGMATH); + break; +#endif default: break; } diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index 94c48316add7..ff4496a6ee18 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -3840,7 +3840,8 @@ CGDebugInfo::getGlobalVariableForwardDeclaration(const VarDecl *VD) { auto Align = getDeclAlignIfRequired(VD, CGM.getContext()); auto *GV = DBuilder.createTempGlobalVariableFwdDecl( DContext, Name, LinkageName, Unit, Line, getOrCreateType(T, Unit), - !VD->isExternallyVisible(), nullptr, TemplateParameters, Align); + !VD->isExternallyVisible(), nullptr, TemplateParameters, + llvm::DINode::FlagZero, Align); FwdDeclReplaceMap.emplace_back( std::piecewise_construct, std::make_tuple(cast(VD->getCanonicalDecl())), @@ -5311,7 +5312,7 @@ void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var, Var->hasLocalLinkage(), true, Expr.empty() ? nullptr : DBuilder.createExpression(Expr), getOrCreateStaticDataMemberDeclarationOrNull(D), TemplateParameters, - Align, Annotations); + llvm::DINode::FlagZero, Align, Annotations); Var->addDebugInfo(GVE); } DeclCache[D->getCanonicalDecl()].reset(GVE); @@ -5399,7 +5400,7 @@ void CGDebugInfo::EmitGlobalVariable(const ValueDecl *VD, const APValue &Init) { GV.reset(DBuilder.createGlobalVariableExpression( DContext, Name, StringRef(), Unit, getLineNumber(VD->getLocation()), Ty, true, true, InitExpr, getOrCreateStaticDataMemberDeclarationOrNull(VarD), - TemplateParameters, Align)); + TemplateParameters, llvm::DINode::FlagZero, Align)); } void CGDebugInfo::EmitExternalVariable(llvm::GlobalVariable *Var, @@ -5417,7 +5418,8 @@ void CGDebugInfo::EmitExternalVariable(llvm::GlobalVariable *Var, llvm::DIGlobalVariableExpression *GVE = DBuilder.createGlobalVariableExpression( DContext, Name, StringRef(), Unit, getLineNumber(D->getLocation()), - Ty, false, false, nullptr, nullptr, nullptr, Align); + Ty, false, false, nullptr, nullptr, nullptr, llvm::DINode::FlagZero, + Align); Var->addDebugInfo(GVE); } diff --git a/clang/lib/Driver/Action.cpp b/clang/lib/Driver/Action.cpp index ead3a23da418..d77b525cd8b0 100644 --- a/clang/lib/Driver/Action.cpp +++ b/clang/lib/Driver/Action.cpp @@ -30,6 +30,7 @@ const char *Action::getClassName(ActionClass AC) { return "api-extractor"; case AnalyzeJobClass: return "analyzer"; case MigrateJobClass: return "migrator"; + case FortranFrontendJobClass: return "fortran-frontend"; case CompileJobClass: return "compiler"; case BackendJobClass: return "backend"; case AssembleJobClass: return "assembler"; @@ -363,6 +364,12 @@ void MigrateJobAction::anchor() {} MigrateJobAction::MigrateJobAction(Action *Input, types::ID OutputType) : JobAction(MigrateJobClass, Input, OutputType) {} +void FortranFrontendJobAction::anchor() {} + +FortranFrontendJobAction::FortranFrontendJobAction(Action *Input, + types::ID OutputType) + : JobAction(FortranFrontendJobClass, Input, OutputType) {} + void CompileJobAction::anchor() {} CompileJobAction::CompileJobAction(Action *Input, types::ID OutputType) diff --git a/clang/lib/Driver/CMakeLists.txt b/clang/lib/Driver/CMakeLists.txt index 18c9b2d042f6..24a795ba09ad 100644 --- a/clang/lib/Driver/CMakeLists.txt +++ b/clang/lib/Driver/CMakeLists.txt @@ -12,6 +12,10 @@ if(WIN32) set(system_libs version) endif() +if(LLVM_ENABLE_CLASSIC_FLANG) + set(CLASSIC_FLANG_FILES ToolChains/ClassicFlang.cpp) +endif() + add_clang_library(clangDriver Action.cpp Compilation.cpp @@ -86,6 +90,7 @@ add_clang_library(clangDriver ToolChains/ZOS.cpp Types.cpp XRayArgs.cpp + ${CLASSIC_FLANG_FILES} DEPENDS ClangDriverOptions diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp index 3f29afd35971..e5a4aa955f63 100644 --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -333,11 +333,30 @@ phases::ID Driver::getFinalPhase(const DerivedArgList &DAL, // -{E,EP,P,M,MM} only run the preprocessor. if (CCCIsCPP() || (PhaseArg = DAL.getLastArg(options::OPT_E)) || +#ifdef ENABLE_CLASSIC_FLANG + (PhaseArg = DAL.getLastArg(options::OPT_fsyntax_only)) || +#endif (PhaseArg = DAL.getLastArg(options::OPT__SLASH_EP)) || (PhaseArg = DAL.getLastArg(options::OPT_M, options::OPT_MM)) || (PhaseArg = DAL.getLastArg(options::OPT__SLASH_P)) || CCGenDiagnostics) { +#ifdef ENABLE_CLASSIC_FLANG + // -fsyntax-only or -E stops Fortran compilation after FortranFrontend + if (IsFlangMode() && (DAL.getLastArg(options::OPT_E) || + DAL.getLastArg(options::OPT_fsyntax_only))) { + FinalPhase = phases::FortranFrontend; + + // if not Fortran, fsyntax_only implies 'Compile' is the FinalPhase + } else if (DAL.getLastArg(options::OPT_fsyntax_only)) { + FinalPhase = phases::Compile; + + // everything else has 'Preprocess' as its FinalPhase + } else { + FinalPhase = phases::Preprocess; + } +#else FinalPhase = phases::Preprocess; +#endif // --precompile only runs up to precompilation. // Options that cause the output of C++20 compiled module interfaces or @@ -347,9 +366,15 @@ phases::ID Driver::getFinalPhase(const DerivedArgList &DAL, (PhaseArg = DAL.getLastArg(options::OPT_fmodule_header, options::OPT_fmodule_header_EQ))) { FinalPhase = phases::Precompile; + +#ifdef ENABLE_CLASSIC_FLANG + // -{analyze,emit-ast} only run up to the compiler. + } else if ((PhaseArg = DAL.getLastArg(options::OPT_print_supported_cpus)) || +#else // -{fsyntax-only,-analyze,emit-ast} only run up to the compiler. } else if ((PhaseArg = DAL.getLastArg(options::OPT_fsyntax_only)) || (PhaseArg = DAL.getLastArg(options::OPT_print_supported_cpus)) || +#endif (PhaseArg = DAL.getLastArg(options::OPT_module_file_info)) || (PhaseArg = DAL.getLastArg(options::OPT_verify_pch)) || (PhaseArg = DAL.getLastArg(options::OPT_rewrite_objc)) || @@ -2481,7 +2506,11 @@ void Driver::BuildInputs(const ToolChain &TC, DerivedArgList &Args, // stdin must be handled specially. if (memcmp(Value, "-", 2) == 0) { if (IsFlangMode()) { +#ifdef ENABLE_CLASSIC_FLANG + Ty = types::TY_C; +#else Ty = types::TY_Fortran; +#endif } else { // If running with -E, treat as a C input (this changes the // builtin macros, for example). This may be overridden by -ObjC @@ -3938,6 +3967,11 @@ void Driver::handleArguments(Compilation &C, DerivedArgList &Args, if (InputArg->isClaimed()) continue; + // Fortran input is preprocessed using the frontend. + if (InitialPhase == phases::FortranFrontend && + FinalPhase == phases::Preprocess) + continue; + // Claim here to avoid the more general unused warning. InputArg->claim(); @@ -4607,6 +4641,13 @@ Action *Driver::ConstructPhaseAction( ModName); return C.MakeAction(Input, OutputTy); } + case phases::FortranFrontend: { + if (Args.hasArg(options::OPT_fsyntax_only)) + return C.MakeAction(Input, + types::TY_Nothing); + return C.MakeAction(Input, + types::TY_LLVM_IR); + } case phases::Compile: { if (Args.hasArg(options::OPT_fsyntax_only)) return C.MakeAction(Input, types::TY_Nothing); diff --git a/clang/lib/Driver/Phases.cpp b/clang/lib/Driver/Phases.cpp index 01598c59bd9e..f0216c5ab7c2 100644 --- a/clang/lib/Driver/Phases.cpp +++ b/clang/lib/Driver/Phases.cpp @@ -16,6 +16,7 @@ const char *phases::getPhaseName(ID Id) { switch (Id) { case Preprocess: return "preprocessor"; case Precompile: return "precompiler"; + case FortranFrontend: return "fortran-frontend"; case Compile: return "compiler"; case Backend: return "backend"; case Assemble: return "assembler"; diff --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp index 7a4319ea680f..8626c338dda3 100644 --- a/clang/lib/Driver/ToolChain.cpp +++ b/clang/lib/Driver/ToolChain.cpp @@ -9,6 +9,7 @@ #include "clang/Driver/ToolChain.h" #include "ToolChains/Arch/ARM.h" #include "ToolChains/Clang.h" +#include "ToolChains/ClassicFlang.h" #include "ToolChains/Flang.h" #include "ToolChains/InterfaceStubs.h" #include "clang/Basic/ObjCRuntime.h" @@ -321,6 +322,16 @@ Tool *ToolChain::getAssemble() const { return Assemble.get(); } +Tool *ToolChain::getFortranFrontend() const { +#ifdef ENABLE_CLASSIC_FLANG + if (!FortranFrontend) + FortranFrontend.reset(new tools::ClassicFlang(*this)); + return FortranFrontend.get(); +#else + llvm_unreachable("Fortran is not supported by this toolchain"); +#endif +} + Tool *ToolChain::getClangAs() const { if (!Assemble) Assemble.reset(new tools::ClangAs(*this)); @@ -412,6 +423,9 @@ Tool *ToolChain::getTool(Action::ActionClass AC) const { return getOffloadPackager(); case Action::LinkerWrapperJobClass: return getLinkerWrapper(); + + case Action::FortranFrontendJobClass: + return getFortranFrontend(); } llvm_unreachable("Invalid tool kind."); @@ -686,13 +700,13 @@ std::string ToolChain::GetStaticLibToolPath() const { types::ID ToolChain::LookupTypeForExtension(StringRef Ext) const { types::ID id = types::lookupTypeForExtension(Ext); - +#ifndef ENABLE_CLASSIC_FLANG // Flang always runs the preprocessor and has no notion of "preprocessed // fortran". Here, TY_PP_Fortran is coerced to TY_Fortran to avoid treating // them differently. if (D.IsFlangMode() && id == types::TY_PP_Fortran) id = types::TY_Fortran; - +#endif return id; } @@ -1035,6 +1049,45 @@ void ToolChain::AddCCKextLibArgs(const ArgList &Args, CmdArgs.push_back("-lcc_kext"); } +void ToolChain::AddFortranStdlibLibArgs(const ArgList &Args, + ArgStringList &CmdArgs) const { + bool staticFlangLibs = false; + bool useOpenMP = false; + + if (Args.hasArg(options::OPT_staticFlangLibs)) { + for (auto *A: Args.filtered(options::OPT_staticFlangLibs)) { + A->claim(); + staticFlangLibs = true; + } + } + + Arg *A = Args.getLastArg(options::OPT_mp, options::OPT_nomp, + options::OPT_fopenmp, options::OPT_fno_openmp); + if (A && + (A->getOption().matches(options::OPT_mp) || + A->getOption().matches(options::OPT_fopenmp))) { + useOpenMP = true; + } + + if (staticFlangLibs) + CmdArgs.push_back("-Bstatic"); + CmdArgs.push_back("-lflang"); + CmdArgs.push_back("-lflangrti"); + CmdArgs.push_back("-lpgmath"); + if (useOpenMP) + CmdArgs.push_back("-lomp"); + else + CmdArgs.push_back("-lompstub"); + if (staticFlangLibs) + CmdArgs.push_back("-Bdynamic"); + + CmdArgs.push_back("-lm"); + CmdArgs.push_back("-lrt"); + + // Allways link Fortran executables with Pthreads + CmdArgs.push_back("-lpthread"); +} + bool ToolChain::isFastMathRuntimeAvailable(const ArgList &Args, std::string &Path) const { // Do not check for -fno-fast-math or -fno-unsafe-math when -Ofast passed diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 3704ed858668..1f7b81a6f04b 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -5096,7 +5096,68 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, } } +#ifdef ENABLE_CLASSIC_FLANG + if (Args.getLastArg(options::OPT_fveclib)) + Args.AddLastArg(CmdArgs, options::OPT_fveclib); + else + CmdArgs.push_back("-fveclib=PGMATH"); +#else Args.AddLastArg(CmdArgs, options::OPT_fveclib); +#endif + + std::string PassRemarkVal(""), PassRemarkOpt(""); + if (Args.getLastArg(options::OPT_Minfoall)) { + PassRemarkVal = ".*"; + Args.ClaimAllArgs(options::OPT_Minfoall); + } else if (Arg *A = Args.getLastArg(options::OPT_Minfo_EQ)) { + for (const StringRef &val : A->getValues()) { + if (val.equals("all")) { + PassRemarkVal = ".*"; + break; + } else if (val.equals("inline") || val.equals("vect")) { + PassRemarkVal += PassRemarkVal.empty() ? "" : "|"; + PassRemarkVal += val; + } else { + D.Diag(diag::err_drv_clang_unsupported_minfo_arg) + << A->getOption().getName() + << val.str(); + break; + } + } + } + PassRemarkOpt = "-pass-remarks=" + PassRemarkVal; + CmdArgs.push_back("-mllvm"); + CmdArgs.push_back(Args.MakeArgString(PassRemarkOpt)); + Args.ClaimAllArgs(options::OPT_Minfo_EQ); + PassRemarkVal.clear(); + PassRemarkOpt.clear(); + + if (Args.getLastArg(options::OPT_Mneginfoall)) { + PassRemarkVal = ".*"; + Args.ClaimAllArgs(options::OPT_Mneginfoall); + } else if (Arg *A = Args.getLastArg(options::OPT_Mneginfo_EQ)) { + for (const StringRef &val : A->getValues()) { + if (val.equals("all")) { + PassRemarkVal = ".*"; + break; + } else if (val.equals("inline") || val.equals("vect")) { + PassRemarkVal += PassRemarkVal.empty() ? "" : "|"; + PassRemarkVal += val; + } else { + D.Diag(diag::err_drv_clang_unsupported_minfo_arg) + << A->getOption().getName() + << val.str(); + break; + } + } + } + PassRemarkOpt = "-pass-remarks-missed=" + PassRemarkVal; + CmdArgs.push_back("-mllvm"); + CmdArgs.push_back(Args.MakeArgString(PassRemarkOpt)); + PassRemarkOpt = "-pass-remarks-analysis=" + PassRemarkVal; + CmdArgs.push_back("-mllvm"); + CmdArgs.push_back(Args.MakeArgString(PassRemarkOpt)); + Args.ClaimAllArgs(options::OPT_Mneginfo_EQ); if (Args.hasFlag(options::OPT_fmerge_all_constants, options::OPT_fno_merge_all_constants, false)) diff --git a/clang/lib/Driver/ToolChains/ClassicFlang.cpp b/clang/lib/Driver/ToolChains/ClassicFlang.cpp new file mode 100644 index 000000000000..a68ec58e5e66 --- /dev/null +++ b/clang/lib/Driver/ToolChains/ClassicFlang.cpp @@ -0,0 +1,1064 @@ +//===-- ClassicFlang.cpp - Flang+LLVM ToolChain Implementations -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "ClassicFlang.h" +#include "CommonArgs.h" +#include "clang/Driver/InputInfo.h" +#include "clang/Basic/CharInfo.h" +#include "clang/Basic/LangOptions.h" +#include "clang/Basic/MacroBuilder.h" +#include "clang/Basic/ObjCRuntime.h" +#include "clang/Basic/TargetInfo.h" +#include "clang/Basic/TargetOptions.h" +#include "clang/Basic/Version.h" +#include "clang/Config/config.h" +#include "clang/Driver/DriverDiagnostic.h" +#include "clang/Driver/Options.h" +#include "clang/Driver/SanitizerArgs.h" +#include "clang/Driver/XRayArgs.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Frontend/Utils.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/Option/ArgList.h" +#include "llvm/Support/CodeGen.h" +#include "llvm/Support/Compression.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/Path.h" +#include "llvm/Support/Process.h" +#include "llvm/Support/TargetParser.h" +#include "llvm/Support/YAMLParser.h" + +#ifdef LLVM_ON_UNIX +#include // For getuid(). +#endif + +using namespace clang::driver; +using namespace clang::driver::tools; +using namespace clang; +using namespace llvm::opt; + +class ClassicFlangMacroBuilder : public MacroBuilder { + ArgStringList &CmdArgs; + const ArgList &DriverArgs; + public: + ClassicFlangMacroBuilder(ArgStringList &UpperCmdArgs, const ArgList &DriverArgs, llvm::raw_string_ostream &Output) + : MacroBuilder(Output), CmdArgs(UpperCmdArgs), DriverArgs(DriverArgs) { + } + virtual void defineMacro(const Twine &Name, const Twine &Value = "1") { + CmdArgs.push_back("-def"); + CmdArgs.push_back(DriverArgs.MakeArgString(Name + Twine('=') + Value)); + } +}; + +void ClassicFlang::ConstructJob(Compilation &C, const JobAction &JA, + const InputInfo &Output, const InputInfoList &Inputs, + const ArgList &Args, const char *LinkingOutput) const { + ArgStringList CommonCmdArgs; + ArgStringList UpperCmdArgs; + ArgStringList LowerCmdArgs; + SmallString<256> Stem; + std::string OutFile; + bool NeedIEEE = false; + bool NeedFastMath = false; + bool NeedRelaxedMath = false; + + // Check number of inputs for sanity. We need at least one input. + assert(Inputs.size() >= 1 && "Must have at least one input."); + + /***** Process file arguments to both parts *****/ + const InputInfo &Input = Inputs[0]; + types::ID InputType = Input.getType(); + // Check file type sanity + assert(types::isAcceptedByFlang(InputType) && "Can only accept Fortran"); + + if (Args.hasArg(options::OPT_fsyntax_only)) { + // For -fsyntax-only produce temp files only + Stem = C.getDriver().GetTemporaryPath("", ""); + } else { + OutFile = Output.getFilename(); + Stem = llvm::sys::path::filename(OutFile); + llvm::sys::path::replace_extension(Stem, ""); + } + + // Add input file name to the compilation line + UpperCmdArgs.push_back(Input.getBaseInput()); + + // Add temporary output for ILM + const char * ILMFile = Args.MakeArgString(Stem + ".ilm"); + LowerCmdArgs.push_back(ILMFile); + C.addTempFile(ILMFile); + + // Generate -cmdline + std::string CmdLine("'+flang"); + // ignore the first argument which reads "--driver-mode=fortran" + for (unsigned i = 1; i < Args.getNumInputArgStrings(); ++i) { + CmdLine.append(" "); + CmdLine.append(Args.getArgString(i)); + } + CmdLine.append("'"); + + CommonCmdArgs.push_back("-cmdline"); + CommonCmdArgs.push_back(Args.MakeArgString(CmdLine)); + + /***** Process common args *****/ + + // Add "inform level" flag + if (Args.hasArg(options::OPT_Minform_EQ)) { + // Parse arguments to set its value + for (Arg *A : Args.filtered(options::OPT_Minform_EQ)) { + A->claim(); + CommonCmdArgs.push_back("-inform"); + CommonCmdArgs.push_back(A->getValue(0)); + } + } else { + // Default value + CommonCmdArgs.push_back("-inform"); + CommonCmdArgs.push_back("warn"); + } + + for (auto Arg : Args.filtered(options::OPT_Msave_on)) { + Arg->claim(); + CommonCmdArgs.push_back("-save"); + } + + for (auto Arg : Args.filtered(options::OPT_Msave_off)) { + Arg->claim(); + CommonCmdArgs.push_back("-nosave"); + } + + // Treat denormalized numbers as zero: On + for (auto Arg : Args.filtered(options::OPT_Mdaz_on)) { + Arg->claim(); + CommonCmdArgs.push_back("-x"); + CommonCmdArgs.push_back("129"); + CommonCmdArgs.push_back("4"); + CommonCmdArgs.push_back("-y"); + CommonCmdArgs.push_back("129"); + CommonCmdArgs.push_back("0x400"); + } + + // Treat denormalized numbers as zero: Off + for (auto Arg : Args.filtered(options::OPT_Mdaz_off)) { + Arg->claim(); + CommonCmdArgs.push_back("-y"); + CommonCmdArgs.push_back("129"); + CommonCmdArgs.push_back("4"); + CommonCmdArgs.push_back("-x"); + CommonCmdArgs.push_back("129"); + CommonCmdArgs.push_back("0x400"); + } + + // Store constants in writable data segment + for (auto Arg : Args.filtered(options::OPT_Mwritable_constants)) { + Arg->claim(); + LowerCmdArgs.push_back("-x"); + LowerCmdArgs.push_back("183"); + LowerCmdArgs.push_back("0x20000000"); + } + + // Bounds checking: On + for (auto Arg : Args.filtered(options::OPT_Mbounds_on)) { + Arg->claim(); + CommonCmdArgs.push_back("-x"); + CommonCmdArgs.push_back("70"); + CommonCmdArgs.push_back("2"); + } + + // Bounds checking: Off + for (auto Arg : Args.filtered(options::OPT_Mbounds_off)) { + Arg->claim(); + CommonCmdArgs.push_back("-y"); + CommonCmdArgs.push_back("70"); + CommonCmdArgs.push_back("2"); + } + + // Generate code allowing recursive subprograms + for (auto Arg : Args.filtered(options::OPT_Mrecursive_on)) { + Arg->claim(); + CommonCmdArgs.push_back("-recursive"); + } + + // Disable recursive subprograms + for (auto Arg : Args.filtered(options::OPT_Mrecursive_off)) { + Arg->claim(); + CommonCmdArgs.push_back("-norecursive"); + } + + // Enable generating reentrant code (disable optimizations that inhibit it) + for (auto Arg : Args.filtered(options::OPT_Mreentrant_on)) { + Arg->claim(); + CommonCmdArgs.push_back("-reentrant"); + } + + // Allow optimizations inhibiting reentrancy + for (auto Arg : Args.filtered(options::OPT_Mreentrant_off)) { + Arg->claim(); + CommonCmdArgs.push_back("-noreentrant"); + } + + // Swap byte order for unformatted IO + for (auto Arg : Args.filtered(options::OPT_Mbyteswapio, options::OPT_byteswapio)) { + Arg->claim(); + CommonCmdArgs.push_back("-x"); + CommonCmdArgs.push_back("125"); + CommonCmdArgs.push_back("2"); + } + + // Contiguous pointer checks + if (Arg *A = Args.getLastArg(options::OPT_fsanitize_EQ)) { + for (const StringRef &val : A->getValues()) { + if (val.equals("discontiguous") || val.equals("undefined") ) { + // -x 54 0x40 -x 54 0x80 -x 54 0x200 + UpperCmdArgs.push_back("-x"); + UpperCmdArgs.push_back("54"); + UpperCmdArgs.push_back("0x2c0"); + + // -fsanitze=discontiguous has no meaning in LLVM, only flang driver needs to + // recognize it. However -fsanitize=undefined needs to be passed on for further + // processing by the non-flang part of the driver. + if (val.equals("discontiguous")) + A->claim(); + break; + } + } + } + + // Treat backslashes as regular characters + for (auto Arg : Args.filtered(options::OPT_fno_backslash, options::OPT_Mbackslash)) { + Arg->claim(); + CommonCmdArgs.push_back("-x"); + CommonCmdArgs.push_back("124"); + CommonCmdArgs.push_back("0x40"); + } + + // Treat backslashes as C-style escape characters + for (auto Arg : Args.filtered(options::OPT_fbackslash, options::OPT_Mnobackslash)) { + Arg->claim(); + CommonCmdArgs.push_back("-y"); + CommonCmdArgs.push_back("124"); + CommonCmdArgs.push_back("0x40"); + } + + // handle OpemMP options + if (auto *A = Args.getLastArg(options::OPT_mp, options::OPT_nomp, + options::OPT_fopenmp, options::OPT_fno_openmp)) { + for (auto Arg : Args.filtered(options::OPT_mp, options::OPT_nomp)) { + Arg->claim(); + } + for (auto Arg : Args.filtered(options::OPT_fopenmp, + options::OPT_fno_openmp)) { + Arg->claim(); + } + + if (A->getOption().matches(options::OPT_mp) || + A->getOption().matches(options::OPT_fopenmp)) { + + CommonCmdArgs.push_back("-mp"); + + // Allocate threadprivate data local to the thread + CommonCmdArgs.push_back("-x"); + CommonCmdArgs.push_back("69"); + CommonCmdArgs.push_back("0x200"); + + // Use the 'fair' schedule as the default static schedule + // for parallel do loops + CommonCmdArgs.push_back("-x"); + CommonCmdArgs.push_back("69"); + CommonCmdArgs.push_back("0x400"); + + // Disable use of native atomic instructions + // for OpenMP atomics pending either a named + // option or a libatomic bundled with flang. + UpperCmdArgs.push_back("-x"); + UpperCmdArgs.push_back("69"); + UpperCmdArgs.push_back("0x1000"); + } + } + + // Align large objects on cache lines + for (auto Arg : Args.filtered(options::OPT_Mcache_align_on)) { + Arg->claim(); + CommonCmdArgs.push_back("-x"); + CommonCmdArgs.push_back("119"); + CommonCmdArgs.push_back("0x10000000"); + LowerCmdArgs.push_back("-x"); + LowerCmdArgs.push_back("129"); + LowerCmdArgs.push_back("0x40000000"); + } + + // Disable special alignment of large objects + for (auto Arg : Args.filtered(options::OPT_Mcache_align_off)) { + Arg->claim(); + CommonCmdArgs.push_back("-y"); + CommonCmdArgs.push_back("119"); + CommonCmdArgs.push_back("0x10000000"); + LowerCmdArgs.push_back("-y"); + LowerCmdArgs.push_back("129"); + LowerCmdArgs.push_back("0x40000000"); + } + + // -Mstack_arrays + for (auto Arg : Args.filtered(options::OPT_Mstackarrays)) { + Arg->claim(); + CommonCmdArgs.push_back("-x"); + CommonCmdArgs.push_back("54"); + CommonCmdArgs.push_back("8"); + } + + // -Memit-dwarf-common-blocks-name, only add xbit to flang2. + for (auto Arg : Args.filtered(options::OPT_Memit_dwarf_common_blocks_name)) { + Arg->claim(); + LowerCmdArgs.push_back("-x"); + LowerCmdArgs.push_back("183"); + LowerCmdArgs.push_back("0x40000000"); + } + + // -Munixlogical, only add xbit to flang2. + for (auto Arg : Args.filtered(options::OPT_Munixlogical)) { + Arg->claim(); + LowerCmdArgs.push_back("-x"); + LowerCmdArgs.push_back("125"); + LowerCmdArgs.push_back("0x8"); + } + + // -g should produce DWARFv2 + for (auto Arg : Args.filtered(options::OPT_g_Flag)) { + Arg->claim(); + CommonCmdArgs.push_back("-x"); + CommonCmdArgs.push_back("120"); + CommonCmdArgs.push_back("0x200"); + } + + // -gdwarf-2 + for (auto Arg : Args.filtered(options::OPT_gdwarf_2)) { + Arg->claim(); + CommonCmdArgs.push_back("-x"); + CommonCmdArgs.push_back("120"); + CommonCmdArgs.push_back("0x200"); + } + + // -gdwarf-3 + for (auto Arg : Args.filtered(options::OPT_gdwarf_3)) { + Arg->claim(); + CommonCmdArgs.push_back("-x"); + CommonCmdArgs.push_back("120"); + CommonCmdArgs.push_back("0x4000"); + } + + // -Mipa has no effect + if (Arg *A = Args.getLastArg(options::OPT_Mipa)) { + getToolChain().getDriver().Diag(diag::warn_drv_clang_unsupported) + << A->getAsString(Args); + } + + // -Minline has no effect + if (Arg *A = Args.getLastArg(options::OPT_Minline_on)) { + getToolChain().getDriver().Diag(diag::warn_drv_clang_unsupported) + << A->getAsString(Args); + } + + // Handle -fdefault-real-8 (and its alias, -r8) and -fno-default-real-8 + if (Arg *A = Args.getLastArg(options::OPT_r8, + options::OPT_fdefault_real_8, + options::OPT_default_real_8_fno)) { + const char * fl; + // For -f version add -x flag, for -fno add -y + if (A->getOption().matches(options::OPT_default_real_8_fno)) { + fl = "-y"; + } else { + fl = "-x"; + } + + for (Arg *A : Args.filtered(options::OPT_r8, + options::OPT_fdefault_real_8, + options::OPT_default_real_8_fno)) { + A->claim(); + } + + UpperCmdArgs.push_back(fl); + UpperCmdArgs.push_back("124"); + UpperCmdArgs.push_back("0x8"); + UpperCmdArgs.push_back(fl); + UpperCmdArgs.push_back("124"); + UpperCmdArgs.push_back("0x80000"); + } + + // Process and claim -i8/-fdefault-integer-8/-fno-default-integer-8 argument + if (Arg *A = Args.getLastArg(options::OPT_i8, + options::OPT_fdefault_integer_8, + options::OPT_default_integer_8_fno)) { + const char * fl; + + if (A->getOption().matches(options::OPT_default_integer_8_fno)) { + fl = "-y"; + } else { + fl = "-x"; + } + + for (Arg *A : Args.filtered(options::OPT_i8, + options::OPT_fdefault_integer_8, + options::OPT_default_integer_8_fno)) { + A->claim(); + } + + UpperCmdArgs.push_back(fl); + UpperCmdArgs.push_back("124"); + UpperCmdArgs.push_back("0x10"); + } + + // Pass an arbitrary flag for first part of Fortran frontend + for (Arg *A : Args.filtered(options::OPT_Wh_EQ)) { + A->claim(); + StringRef Value = A->getValue(); + SmallVector PassArgs; + Value.split(PassArgs, StringRef(",")); + for (StringRef PassArg : PassArgs) { + UpperCmdArgs.push_back(Args.MakeArgString(PassArg)); + } + } + + // Flush to zero mode + // Disabled by default, but can be enabled by a switch + if (Args.hasArg(options::OPT_Mflushz_on)) { + // For -Mflushz set -x 129 2 for second part of Fortran frontend + for (Arg *A: Args.filtered(options::OPT_Mflushz_on)) { + A->claim(); + LowerCmdArgs.push_back("-x"); + LowerCmdArgs.push_back("129"); + LowerCmdArgs.push_back("2"); + } + } else { + LowerCmdArgs.push_back("-y"); + LowerCmdArgs.push_back("129"); + LowerCmdArgs.push_back("2"); + for (Arg *A: Args.filtered(options::OPT_Mflushz_off)) { + A->claim(); + } + } + + // Enable FMA + for (Arg *A: Args.filtered(options::OPT_Mfma_on, options::OPT_fma)) { + A->claim(); + LowerCmdArgs.push_back("-x"); + LowerCmdArgs.push_back("172"); + LowerCmdArgs.push_back("0x40000000"); + LowerCmdArgs.push_back("-x"); + LowerCmdArgs.push_back("179"); + LowerCmdArgs.push_back("1"); + } + + // Disable FMA + for (Arg *A: Args.filtered(options::OPT_Mfma_off, options::OPT_nofma)) { + A->claim(); + LowerCmdArgs.push_back("-x"); + LowerCmdArgs.push_back("171"); + LowerCmdArgs.push_back("0x40000000"); + LowerCmdArgs.push_back("-x"); + LowerCmdArgs.push_back("178"); + LowerCmdArgs.push_back("1"); + } + + // For -fPIC set -x 62 8 for second part of Fortran frontend + for (Arg *A: Args.filtered(options::OPT_fPIC)) { + A->claim(); + LowerCmdArgs.push_back("-x"); + LowerCmdArgs.push_back("62"); + LowerCmdArgs.push_back("8"); + } + + StringRef OptOStr("0"); + if (Arg *A = Args.getLastArg(options::OPT_O_Group)) { + if (A->getOption().matches(options::OPT_O4)) { + OptOStr = "4"; // FIXME what should this be? + } else if (A->getOption().matches(options::OPT_Ofast)) { + OptOStr = "2"; // FIXME what should this be? + } else if (A->getOption().matches(options::OPT_O0)) { + // intentionally do nothing + } else { + assert(A->getOption().matches(options::OPT_O) && "Must have a -O flag"); + StringRef S(A->getValue()); + if ((S == "s") || (S == "z")) { + // -Os = size; -Oz = more size + OptOStr = "2"; // FIXME -Os|-Oz => -opt ? + } else if ((S == "1") || (S == "2") || (S == "3")) { + OptOStr = S; + } else { + OptOStr = "4"; + } + } + } + unsigned OptLevel = std::stoi(OptOStr.str()); + + if (Args.hasArg(options::OPT_g_Group)) { + // pass -g to lower and upper + CommonCmdArgs.push_back("-debug"); + } + + /* Pick the last among conflicting flags, if a positive and negative flag + exists for ex. "-ffast-math -fno-fast-math" they get nullified. Also any + previously overwritten flag remains that way. + For ex. "-Kieee -ffast-math -fno-fast-math". -Kieee gets overwritten by + -ffast-math which then gets negated by -fno-fast-math, finally behaving as + if none of those flags were passed. + */ + for(Arg *A: Args.filtered(options::OPT_ffast_math, options::OPT_fno_fast_math, + options::OPT_Ofast, options::OPT_Kieee_off, + options::OPT_Kieee_on, options::OPT_frelaxed_math)) { + if (A->getOption().matches(options::OPT_ffast_math) || + A->getOption().matches(options::OPT_Ofast)) { + NeedIEEE = NeedRelaxedMath = false; + NeedFastMath = true; + } else if (A->getOption().matches(options::OPT_Kieee_on)) { + NeedFastMath = NeedRelaxedMath = false; + NeedIEEE = true; + } else if (A->getOption().matches(options::OPT_frelaxed_math)) { + NeedFastMath = NeedIEEE = false; + NeedRelaxedMath = true; + } else if (A->getOption().matches(options::OPT_fno_fast_math)) { + NeedFastMath = false; + } else if (A->getOption().matches(options::OPT_Kieee_off)) { + NeedIEEE = false; + } + A->claim(); + } + + if (NeedFastMath) { + // Lower: -x 216 1 + LowerCmdArgs.push_back("-x"); + LowerCmdArgs.push_back("216"); + LowerCmdArgs.push_back("1"); + // Lower: -ieee 0 + CommonCmdArgs.push_back("-ieee"); + CommonCmdArgs.push_back("0"); + } else if (NeedIEEE) { + // Common: -y 129 2 + CommonCmdArgs.push_back("-y"); + CommonCmdArgs.push_back("129"); + CommonCmdArgs.push_back("2"); + // Lower: -x 6 0x100 + LowerCmdArgs.push_back("-x"); + LowerCmdArgs.push_back("6"); + LowerCmdArgs.push_back("0x100"); + // Lower: -x 42 0x400000 + LowerCmdArgs.push_back("-x"); + LowerCmdArgs.push_back("42"); + LowerCmdArgs.push_back("0x400000"); + // Lower: -y 129 4 + LowerCmdArgs.push_back("-y"); + LowerCmdArgs.push_back("129"); + LowerCmdArgs.push_back("4"); + // Lower: -x 129 0x400 + LowerCmdArgs.push_back("-x"); + LowerCmdArgs.push_back("129"); + LowerCmdArgs.push_back("0x400"); + // Lower: -y 216 1 (OPT_fno_fast_math) + LowerCmdArgs.push_back("-y"); + LowerCmdArgs.push_back("216"); + LowerCmdArgs.push_back("1"); + // Lower: -ieee 1 + CommonCmdArgs.push_back("-ieee"); + CommonCmdArgs.push_back("1"); + } else if (NeedRelaxedMath) { + // Lower: -x 15 0x400 + LowerCmdArgs.push_back("-x"); + LowerCmdArgs.push_back("15"); + LowerCmdArgs.push_back("0x400"); + // Lower: -y 216 1 (OPT_fno_fast_math) + LowerCmdArgs.push_back("-y"); + LowerCmdArgs.push_back("216"); + LowerCmdArgs.push_back("1"); + // Lower: -ieee 0 + CommonCmdArgs.push_back("-ieee"); + CommonCmdArgs.push_back("0"); + } else { + // Lower: -ieee 0 + CommonCmdArgs.push_back("-ieee"); + CommonCmdArgs.push_back("0"); + } + + /***** Upper part of the Fortran frontend *****/ + + // TODO do we need to invoke this under GDB sometimes? + const char *UpperExec = Args.MakeArgString(getToolChain().GetProgramPath("flang1")); + + UpperCmdArgs.push_back("-opt"); UpperCmdArgs.push_back(Args.MakeArgString(OptOStr)); + UpperCmdArgs.push_back("-terse"); UpperCmdArgs.push_back("1"); + UpperCmdArgs.push_back("-inform"); UpperCmdArgs.push_back("warn"); + UpperCmdArgs.push_back("-nohpf"); + UpperCmdArgs.push_back("-nostatic"); + UpperCmdArgs.append(CommonCmdArgs.begin(), CommonCmdArgs.end()); // Append common arguments + UpperCmdArgs.push_back("-x"); UpperCmdArgs.push_back("19"); UpperCmdArgs.push_back("0x400000"); + UpperCmdArgs.push_back("-quad"); + UpperCmdArgs.push_back("-x"); UpperCmdArgs.push_back("68"); UpperCmdArgs.push_back("0x1"); + UpperCmdArgs.push_back("-x"); UpperCmdArgs.push_back("59"); UpperCmdArgs.push_back("4"); + UpperCmdArgs.push_back("-x"); UpperCmdArgs.push_back("15"); UpperCmdArgs.push_back("2"); + UpperCmdArgs.push_back("-x"); UpperCmdArgs.push_back("49"); UpperCmdArgs.push_back("0x400004"); + UpperCmdArgs.push_back("-x"); UpperCmdArgs.push_back("51"); UpperCmdArgs.push_back("0x20"); + UpperCmdArgs.push_back("-x"); UpperCmdArgs.push_back("57"); UpperCmdArgs.push_back("0x4c"); + UpperCmdArgs.push_back("-x"); UpperCmdArgs.push_back("58"); UpperCmdArgs.push_back("0x10000"); + UpperCmdArgs.push_back("-x"); UpperCmdArgs.push_back("124"); UpperCmdArgs.push_back("0x1000"); + UpperCmdArgs.push_back("-tp"); UpperCmdArgs.push_back("px"); + UpperCmdArgs.push_back("-x"); UpperCmdArgs.push_back("57"); UpperCmdArgs.push_back("0xfb0000"); + UpperCmdArgs.push_back("-x"); UpperCmdArgs.push_back("58"); UpperCmdArgs.push_back("0x78031040"); + UpperCmdArgs.push_back("-x"); UpperCmdArgs.push_back("47"); UpperCmdArgs.push_back("0x08"); + UpperCmdArgs.push_back("-x"); UpperCmdArgs.push_back("48"); UpperCmdArgs.push_back("4608"); + UpperCmdArgs.push_back("-x"); UpperCmdArgs.push_back("49"); UpperCmdArgs.push_back("0x100"); + if (OptLevel >= 2) { + UpperCmdArgs.push_back("-x"); + UpperCmdArgs.push_back("70"); + UpperCmdArgs.push_back("0x6c00"); + UpperCmdArgs.push_back("-x"); + UpperCmdArgs.push_back("119"); + UpperCmdArgs.push_back("0x10000000"); + UpperCmdArgs.push_back("-x"); + UpperCmdArgs.push_back("129"); + UpperCmdArgs.push_back("2"); + UpperCmdArgs.push_back("-x"); + UpperCmdArgs.push_back("47"); + UpperCmdArgs.push_back("0x400000"); + UpperCmdArgs.push_back("-x"); + UpperCmdArgs.push_back("52"); + UpperCmdArgs.push_back("2"); + } + + // Add system include arguments. + getToolChain().AddFlangSystemIncludeArgs(Args, UpperCmdArgs); + + // Use clang's predefined macros + DiagnosticsEngine DE(new DiagnosticIDs(), new DiagnosticOptions, new IgnoringDiagConsumer()); + std::shared_ptr TO = std::make_shared(); + TO->Triple = getToolChain().getEffectiveTriple().getTriple(); + std::shared_ptr TI(clang::TargetInfo::CreateTargetInfo(DE, TO)); + std::string PredefineBuffer; + llvm::raw_string_ostream Predefines(PredefineBuffer); + ClassicFlangMacroBuilder Builder(UpperCmdArgs, Args, Predefines); + + LangOptions LO; + VersionTuple VT = getToolChain().computeMSVCVersion(&getToolChain().getDriver(), Args); + if (!VT.empty()) { + // Set the MSCompatibility version. Subminor version has 5 decimal digits. + // Minor and major versions have 2 decimal digits each. + LO.MSCompatibilityVersion = VT.getMajor() * 10000000 + + VT.getMinor().value_or(0) * 100000 + + VT.getSubminor().value_or(0); + } + + // Define Target specific macros like __linux__ + TI->getTargetDefines(LO, Builder); + + Builder.defineMacro("__SIZE_TYPE__", TargetInfo::getTypeName(TI->getSizeType())); + Builder.defineMacro("__PTRDIFF_TYPE__", TargetInfo::getTypeName(TI->getPtrDiffType(0))); + + if (TI->getPointerWidth(0) == 64 && TI->getLongWidth() == 64 + && TI->getIntWidth() == 32) { + Builder.defineMacro("_LP64"); + Builder.defineMacro("__LP64__"); + } + + if (TI->getPointerWidth(0) == 32 && TI->getLongWidth() == 32 + && TI->getIntWidth() == 32) { + Builder.defineMacro("_ILP32"); + Builder.defineMacro("__ILP32__"); + } + + DefineTypeSize("__LONG_MAX__", TargetInfo::SignedLong, *TI, Builder); + + // Add additional predefined macros + switch (getToolChain().getEffectiveTriple().getArch()) { + case llvm::Triple::aarch64: + UpperCmdArgs.push_back("-def"); UpperCmdArgs.push_back("__ARM_ARCH__=8"); + break; + case llvm::Triple::x86_64: + UpperCmdArgs.push_back("-def"); UpperCmdArgs.push_back("__amd_64__amd64__"); + UpperCmdArgs.push_back("-def"); UpperCmdArgs.push_back("__k8"); + UpperCmdArgs.push_back("-def"); UpperCmdArgs.push_back("__k8__"); + break; + default: /* generic 64-bit */ + ; + } + UpperCmdArgs.push_back("-def"); UpperCmdArgs.push_back("__THROW="); + UpperCmdArgs.push_back("-def"); UpperCmdArgs.push_back("__extension__="); + UpperCmdArgs.push_back("-def"); UpperCmdArgs.push_back("__PGLLVM__"); + + // Enable preprocessor + if (Args.hasArg(options::OPT_Mpreprocess) || + Args.hasArg(options::OPT_cpp) || + Args.hasArg(options::OPT_E) || + types::getPreprocessedType(InputType) != types::TY_INVALID) { + UpperCmdArgs.push_back("-preprocess"); + for (auto Arg : Args.filtered(options::OPT_Mpreprocess, options::OPT_cpp, options::OPT_E)) { + Arg->claim(); + } + + // When -E option is provided, run only the fortran preprocessor. + // Only in -E mode, consume -P if it exists + if (Args.hasArg(options::OPT_E)) { + UpperCmdArgs.push_back("-es"); + // Line marker mode is disabled + if (Args.hasArg(options::OPT_P)) { + Args.ClaimAllArgs(options::OPT_P); + } else { + // -pp enables line marker mode in fortran preprocessor + UpperCmdArgs.push_back("-pp"); + } + } + } + + // Enable standards checking + if (Args.hasArg(options::OPT_Mstandard)) { + UpperCmdArgs.push_back("-standard"); + for (auto Arg : Args.filtered(options::OPT_Mstandard)) { + Arg->claim(); + } + } + + // Free or fixed form file + if (Args.hasArg(options::OPT_fortran_format_Group)) { + // Override file name suffix, scan arguments for that + for (Arg *A : Args.filtered(options::OPT_fortran_format_Group)) { + A->claim(); + switch (A->getOption().getID()) { + default: + llvm_unreachable("missed a case"); + case options::OPT_ffixed_form: + case options::OPT_free_form_off: + case options::OPT_Mfixed: + case options::OPT_Mfree_off: + case options::OPT_Mfreeform_off: + UpperCmdArgs.push_back("-nofreeform"); + break; + case options::OPT_ffree_form: + case options::OPT_fixed_form_off: + case options::OPT_Mfree_on: + case options::OPT_Mfreeform_on: + UpperCmdArgs.push_back("-freeform"); + break; + } + } + } else { + // Deduce format from file name suffix + if (types::isFreeFormFortran(InputType)) { + UpperCmdArgs.push_back("-freeform"); + } else { + UpperCmdArgs.push_back("-nofreeform"); + } + } + + // Extend lines to 132 characters + for (auto Arg : Args.filtered(options::OPT_Mextend)) { + Arg->claim(); + UpperCmdArgs.push_back("-extend"); + } + + for (auto Arg : Args.filtered(options::OPT_ffixed_line_length_VALUE)) { + StringRef Value = Arg->getValue(); + if (Value == "72") { + Arg->claim(); + } else if (Value == "132") { + Arg->claim(); + UpperCmdArgs.push_back("-extend"); + } else { + getToolChain().getDriver().Diag(diag::err_drv_unsupported_fixed_line_length) + << Arg->getAsString(Args); + } + } + + // Add user-defined include directories + for (auto Arg : Args.filtered(options::OPT_I)) { + Arg->claim(); + UpperCmdArgs.push_back("-idir"); + UpperCmdArgs.push_back(Arg->getValue(0)); + } + + // Add user-defined module directories + for (auto Arg : Args.filtered(options::OPT_ModuleDir, options::OPT_J)) { + Arg->claim(); + UpperCmdArgs.push_back("-moddir"); + UpperCmdArgs.push_back(Arg->getValue(0)); + } + + // "Define" preprocessor flags + for (auto Arg : Args.filtered(options::OPT_D)) { + Arg->claim(); + UpperCmdArgs.push_back("-def"); + UpperCmdArgs.push_back(Arg->getValue(0)); + } + + // "Define" preprocessor flags + for (auto Arg : Args.filtered(options::OPT_U)) { + Arg->claim(); + UpperCmdArgs.push_back("-undef"); + UpperCmdArgs.push_back(Arg->getValue(0)); + } + + UpperCmdArgs.push_back("-vect"); UpperCmdArgs.push_back("48"); + + // Semantics for assignments to allocatables + if (Arg *A = Args.getLastArg(options::OPT_Mallocatable_EQ)) { + // Argument is passed explicitly + StringRef Value = A->getValue(); + if (Value == "03") { // Enable Fortran 2003 semantics + UpperCmdArgs.push_back("-x"); // Set XBIT + } else if (Value == "95") { // Enable Fortran 2003 semantics + UpperCmdArgs.push_back("-y"); // Unset XBIT + } else { + getToolChain().getDriver().Diag(diag::err_drv_invalid_allocatable_mode) + << A->getAsString(Args); + } + } else { // No argument passed + UpperCmdArgs.push_back("-x"); // Default is 03 + } + UpperCmdArgs.push_back("54"); UpperCmdArgs.push_back("1"); // XBIT value + + UpperCmdArgs.push_back("-x"); UpperCmdArgs.push_back("70"); UpperCmdArgs.push_back("0x40000000"); + UpperCmdArgs.push_back("-y"); UpperCmdArgs.push_back("163"); UpperCmdArgs.push_back("0xc0000000"); + UpperCmdArgs.push_back("-x"); UpperCmdArgs.push_back("189"); UpperCmdArgs.push_back("0x10"); + + // Enable NULL pointer checking + if (Args.hasArg(options::OPT_Mchkptr)) { + UpperCmdArgs.push_back("-x"); + UpperCmdArgs.push_back("70"); + UpperCmdArgs.push_back("4"); + for (auto Arg : Args.filtered(options::OPT_Mchkptr)) { + Arg->claim(); + } + } + + // Set a -x flag for first part of Fortran frontend + for (Arg *A : Args.filtered(options::OPT_Hx_EQ)) { + A->claim(); + StringRef Value = A->getValue(); + auto XFlag = Value.split(","); + UpperCmdArgs.push_back("-x"); + UpperCmdArgs.push_back(Args.MakeArgString(XFlag.first)); + UpperCmdArgs.push_back(Args.MakeArgString(XFlag.second)); + } + + // Set a -y flag for first part of Fortran frontend + for (Arg *A : Args.filtered(options::OPT_Hy_EQ)) { + A->claim(); + StringRef Value = A->getValue(); + auto XFlag = Value.split(","); + UpperCmdArgs.push_back("-y"); + UpperCmdArgs.push_back(Args.MakeArgString(XFlag.first)); + UpperCmdArgs.push_back(Args.MakeArgString(XFlag.second)); + } + + // Set a -q (debug) flag for first part of Fortran frontend + for (Arg *A : Args.filtered(options::OPT_Hq_EQ)) { + A->claim(); + StringRef Value = A->getValue(); + auto XFlag = Value.split(","); + UpperCmdArgs.push_back("-q"); + UpperCmdArgs.push_back(Args.MakeArgString(XFlag.first)); + UpperCmdArgs.push_back(Args.MakeArgString(XFlag.second)); + } + + // Set a -qq (debug) flag for first part of Fortran frontend + for (Arg *A : Args.filtered(options::OPT_Hqq_EQ)) { + A->claim(); + StringRef Value = A->getValue(); + auto XFlag = Value.split(","); + UpperCmdArgs.push_back("-qq"); + UpperCmdArgs.push_back(Args.MakeArgString(XFlag.first)); + UpperCmdArgs.push_back(Args.MakeArgString(XFlag.second)); + } + + const char * STBFile = Args.MakeArgString(Stem + ".stb"); + C.addTempFile(STBFile); + UpperCmdArgs.push_back("-stbfile"); + UpperCmdArgs.push_back(STBFile); + + const char * ModuleExportFile = Args.MakeArgString(Stem + ".cmod"); + C.addTempFile(ModuleExportFile); + UpperCmdArgs.push_back("-modexport"); + UpperCmdArgs.push_back(ModuleExportFile); + + const char * ModuleIndexFile = Args.MakeArgString(Stem + ".cmdx"); + C.addTempFile(ModuleIndexFile); + UpperCmdArgs.push_back("-modindex"); + UpperCmdArgs.push_back(ModuleIndexFile); + + UpperCmdArgs.push_back("-output"); + UpperCmdArgs.push_back(ILMFile); + + SmallString<256> Path; + if(Args.getAllArgValues(options::OPT_fopenmp_targets_EQ).size() > 0) { + SmallString<128> TargetInfo; + Path = llvm::sys::path::parent_path(Output.getFilename()); + Arg* Tgts = Args.getLastArg(options::OPT_fopenmp_targets_EQ); + assert(Tgts && Tgts->getNumValues() && + "OpenMP offloading has to have targets specified."); + for (unsigned i = 0; i < Tgts->getNumValues(); ++i) { + if (i) + TargetInfo += ','; + llvm::Triple T(Tgts->getValue(i)); + TargetInfo += T.getTriple(); + } + UpperCmdArgs.push_back("-fopenmp-targets"); + UpperCmdArgs.push_back(Args.MakeArgString(TargetInfo.str())); + } + + C.addCommand(std::make_unique(JA, *this, ResponseFileSupport::AtFileUTF8(), UpperExec, UpperCmdArgs, Inputs)); + + // For -fsyntax-only or -E that is it + if (Args.hasArg(options::OPT_fsyntax_only) || + Args.hasArg(options::OPT_E)) return; + + /***** Lower part of Fortran frontend *****/ + + const char *LowerExec = Args.MakeArgString(getToolChain().GetProgramPath("flang2")); + + // TODO FLANG arg handling + LowerCmdArgs.push_back("-fn"); LowerCmdArgs.push_back(Input.getBaseInput()); + LowerCmdArgs.push_back("-opt"); LowerCmdArgs.push_back(Args.MakeArgString(OptOStr)); + LowerCmdArgs.push_back("-terse"); LowerCmdArgs.push_back("1"); + LowerCmdArgs.push_back("-inform"); LowerCmdArgs.push_back("warn"); + LowerCmdArgs.append(CommonCmdArgs.begin(), CommonCmdArgs.end()); // Append common arguments + LowerCmdArgs.push_back("-x"); LowerCmdArgs.push_back("68"); LowerCmdArgs.push_back("0x1"); + LowerCmdArgs.push_back("-x"); LowerCmdArgs.push_back("51"); LowerCmdArgs.push_back("0x20"); + LowerCmdArgs.push_back("-x"); LowerCmdArgs.push_back("119"); LowerCmdArgs.push_back("0xa10000"); + LowerCmdArgs.push_back("-x"); LowerCmdArgs.push_back("122"); LowerCmdArgs.push_back("0x40"); + LowerCmdArgs.push_back("-x"); LowerCmdArgs.push_back("123"); LowerCmdArgs.push_back("0x1000"); + LowerCmdArgs.push_back("-x"); LowerCmdArgs.push_back("127"); LowerCmdArgs.push_back("4"); + LowerCmdArgs.push_back("-x"); LowerCmdArgs.push_back("127"); LowerCmdArgs.push_back("17"); + LowerCmdArgs.push_back("-x"); LowerCmdArgs.push_back("19"); LowerCmdArgs.push_back("0x400000"); + LowerCmdArgs.push_back("-x"); LowerCmdArgs.push_back("28"); LowerCmdArgs.push_back("0x40000"); + LowerCmdArgs.push_back("-x"); LowerCmdArgs.push_back("120"); LowerCmdArgs.push_back("0x10000000"); + LowerCmdArgs.push_back("-x"); LowerCmdArgs.push_back("70"); LowerCmdArgs.push_back("0x8000"); + LowerCmdArgs.push_back("-x"); LowerCmdArgs.push_back("122"); LowerCmdArgs.push_back("1"); + LowerCmdArgs.push_back("-x"); LowerCmdArgs.push_back("125"); LowerCmdArgs.push_back("0x20000"); + LowerCmdArgs.push_back("-x"); LowerCmdArgs.push_back("164"); LowerCmdArgs.push_back("0x800000"); + LowerCmdArgs.push_back("-quad"); + LowerCmdArgs.push_back("-x"); LowerCmdArgs.push_back("59"); LowerCmdArgs.push_back("4"); + LowerCmdArgs.push_back("-tp"); LowerCmdArgs.push_back("px"); + LowerCmdArgs.push_back("-x"); LowerCmdArgs.push_back("120"); LowerCmdArgs.push_back("0x1000"); // debug lite + LowerCmdArgs.push_back("-x"); LowerCmdArgs.push_back("124"); LowerCmdArgs.push_back("0x1400"); + LowerCmdArgs.push_back("-y"); LowerCmdArgs.push_back("15"); LowerCmdArgs.push_back("2"); + LowerCmdArgs.push_back("-x"); LowerCmdArgs.push_back("57"); LowerCmdArgs.push_back("0x3b0000"); + LowerCmdArgs.push_back("-x"); LowerCmdArgs.push_back("58"); LowerCmdArgs.push_back("0x48000000"); + LowerCmdArgs.push_back("-x"); LowerCmdArgs.push_back("49"); LowerCmdArgs.push_back("0x100"); + LowerCmdArgs.push_back("-astype"); LowerCmdArgs.push_back("0"); + LowerCmdArgs.push_back("-x"); LowerCmdArgs.push_back("183"); LowerCmdArgs.push_back("4"); + LowerCmdArgs.push_back("-x"); LowerCmdArgs.push_back("121"); LowerCmdArgs.push_back("0x800"); + LowerCmdArgs.push_back("-x"); LowerCmdArgs.push_back("54"); LowerCmdArgs.push_back("0x10"); + LowerCmdArgs.push_back("-x"); LowerCmdArgs.push_back("70"); LowerCmdArgs.push_back("0x40000000"); + LowerCmdArgs.push_back("-x"); LowerCmdArgs.push_back("249"); LowerCmdArgs.push_back("150"); // LLVM version + LowerCmdArgs.push_back("-x"); LowerCmdArgs.push_back("124"); LowerCmdArgs.push_back("1"); + LowerCmdArgs.push_back("-y"); LowerCmdArgs.push_back("163"); LowerCmdArgs.push_back("0xc0000000"); + LowerCmdArgs.push_back("-x"); LowerCmdArgs.push_back("189"); LowerCmdArgs.push_back("0x10"); + LowerCmdArgs.push_back("-y"); LowerCmdArgs.push_back("189"); LowerCmdArgs.push_back("0x4000000"); + + // Remove "noinline" attriblute + LowerCmdArgs.push_back("-x"); LowerCmdArgs.push_back("183"); LowerCmdArgs.push_back("0x10"); + + // Set a -x flag for second part of Fortran frontend + for (Arg *A : Args.filtered(options::OPT_Mx_EQ)) { + A->claim(); + StringRef Value = A->getValue(); + auto XFlag = Value.split(","); + LowerCmdArgs.push_back("-x"); + LowerCmdArgs.push_back(Args.MakeArgString(XFlag.first)); + LowerCmdArgs.push_back(Args.MakeArgString(XFlag.second)); + } + + // Set a -y flag for second part of Fortran frontend + for (Arg *A : Args.filtered(options::OPT_My_EQ)) { + A->claim(); + StringRef Value = A->getValue(); + auto XFlag = Value.split(","); + LowerCmdArgs.push_back("-y"); + LowerCmdArgs.push_back(Args.MakeArgString(XFlag.first)); + LowerCmdArgs.push_back(Args.MakeArgString(XFlag.second)); + } + + // Set a -q (debug) flag for second part of Fortran frontend + for (Arg *A : Args.filtered(options::OPT_Mq_EQ)) { + A->claim(); + StringRef Value = A->getValue(); + auto XFlag = Value.split(","); + LowerCmdArgs.push_back("-q"); + LowerCmdArgs.push_back(Args.MakeArgString(XFlag.first)); + LowerCmdArgs.push_back(Args.MakeArgString(XFlag.second)); + } + + // Set a -qq (debug) flag for second part of Fortran frontend + for (Arg *A : Args.filtered(options::OPT_Mqq_EQ)) { + A->claim(); + StringRef Value = A->getValue(); + auto XFlag = Value.split(","); + LowerCmdArgs.push_back("-qq"); + LowerCmdArgs.push_back(Args.MakeArgString(XFlag.first)); + LowerCmdArgs.push_back(Args.MakeArgString(XFlag.second)); + } + + // Pass an arbitrary flag for second part of Fortran frontend + for (Arg *A : Args.filtered(options::OPT_Wm_EQ)) { + A->claim(); + StringRef Value = A->getValue(); + SmallVector PassArgs; + Value.split(PassArgs, StringRef(",")); + for (StringRef PassArg : PassArgs) { + LowerCmdArgs.push_back(Args.MakeArgString(PassArg)); + } + } + + LowerCmdArgs.push_back("-stbfile"); + LowerCmdArgs.push_back(STBFile); + + Path = llvm::sys::path::parent_path(Output.getFilename()); + bool IsOpenMPDevice = JA.isDeviceOffloading(Action::OFK_OpenMP); + + /* OpenMP GPU Offload */ + if(Args.getAllArgValues(options::OPT_fopenmp_targets_EQ).size() > 0) { + SmallString<128> TargetInfo;//("-fopenmp-targets "); + SmallString<256> TargetInfoAsm;//("-fopenmp-targets-asm "); + + Arg* Tgts = Args.getLastArg(options::OPT_fopenmp_targets_EQ); + assert(Tgts && Tgts->getNumValues() && + "OpenMP offloading has to have targets specified."); + for (unsigned i = 0; i < Tgts->getNumValues(); ++i) { + if (i) + TargetInfo += ','; + // We need to get the string from the triple because it may be not exactly + // the same as the one we get directly from the arguments. + llvm::Triple T(Tgts->getValue(i)); + TargetInfo += T.getTriple(); + // We also need to give a output file + TargetInfoAsm += Path; + TargetInfoAsm += "/"; + TargetInfoAsm += Stem; + TargetInfoAsm += "-"; + TargetInfoAsm += T.getTriple(); + TargetInfoAsm += ".ll"; + } + // The driver is aware that flang2 can generate multiple files at the same time. + // We mimic it here by exchanging the output files. + // The driver always uses the output file of -asm. + LowerCmdArgs.push_back("-fopenmp-targets"); + LowerCmdArgs.push_back(Args.MakeArgString(TargetInfo.str())); + if(IsOpenMPDevice) { + LowerCmdArgs.push_back("-fopenmp-targets-asm"); + LowerCmdArgs.push_back(Args.MakeArgString(OutFile)); + LowerCmdArgs.push_back("-asm"); + LowerCmdArgs.push_back(Args.MakeArgString(TargetInfoAsm.str())); + } else { + LowerCmdArgs.push_back("-fopenmp-targets-asm"); + LowerCmdArgs.push_back(Args.MakeArgString(TargetInfoAsm.str())); + LowerCmdArgs.push_back("-asm"); + LowerCmdArgs.push_back(Args.MakeArgString(OutFile)); + } + } else { + LowerCmdArgs.push_back("-asm"); + LowerCmdArgs.push_back(Args.MakeArgString(OutFile)); + } + + C.addCommand(std::make_unique(JA, *this, ResponseFileSupport::AtFileUTF8(), LowerExec, LowerCmdArgs, Inputs)); +} + diff --git a/clang/lib/Driver/ToolChains/ClassicFlang.h b/clang/lib/Driver/ToolChains/ClassicFlang.h new file mode 100644 index 000000000000..23ea1fe6b95d --- /dev/null +++ b/clang/lib/Driver/ToolChains/ClassicFlang.h @@ -0,0 +1,49 @@ +//===--- ClassicFlang.h - Flang ToolChain Implementations -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_ClassicFlang_H +#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_ClassicFlang_H + +#include "MSVC.h" +#include "clang/Basic/DebugInfoOptions.h" +#include "clang/Driver/Driver.h" +#include "clang/Driver/Tool.h" +#include "clang/Driver/Types.h" +#include "llvm/ADT/Triple.h" +#include "llvm/Option/Option.h" +#include "llvm/Support/raw_ostream.h" + +namespace clang { +namespace driver { + +namespace tools { + +/// \brief Flang Fortran frontend +class LLVM_LIBRARY_VISIBILITY ClassicFlang : public Tool { +public: + ClassicFlang(const ToolChain &TC) + : Tool("flang:frontend", + "Fortran frontend to LLVM", TC) {} + + bool hasGoodDiagnostics() const override { return true; } + bool hasIntegratedAssembler() const override { return false; } + bool hasIntegratedCPP() const override { return false; } + + void ConstructJob(Compilation &C, const JobAction &JA, + const InputInfo &Output, const InputInfoList &Inputs, + const llvm::opt::ArgList &TCArgs, + const char *LinkingOutput) const override; +}; + +} // end namespace tools + +} // end namespace driver +} // end namespace clang + +#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_ClassicFlang_H diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp index 443725f7d8a8..84e9233a4aab 100644 --- a/clang/lib/Driver/ToolChains/CommonArgs.cpp +++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp @@ -120,6 +120,23 @@ static void renderRemarksHotnessOptions(const ArgList &Args, Twine("--plugin-opt=opt-remarks-hotness-threshold=") + A->getValue())); } +/// \brief Determine if Fortran "main" object is needed +static bool needFortranMain(const Driver &D, const ArgList &Args) { + return (needFortranLibs(D, Args) + && (!Args.hasArg(options::OPT_Mnomain) || + !Args.hasArg(options::OPT_no_fortran_main))); +} + +/// \brief Determine if Fortran link libraies are needed +bool tools::needFortranLibs(const Driver &D, const ArgList &Args) { + if (D.IsFlangMode() && !Args.hasArg(options::OPT_nostdlib) && + !Args.hasArg(options::OPT_noFlangLibs)) { + return true; + } + + return false; +} + void tools::addPathIfExists(const Driver &D, const Twine &Path, ToolChain::path_list &Paths) { if (D.getVFS().exists(Path)) @@ -215,6 +232,7 @@ void tools::AddLinkerInputs(const ToolChain &TC, const InputInfoList &Inputs, const ArgList &Args, ArgStringList &CmdArgs, const JobAction &JA) { const Driver &D = TC.getDriver(); + bool SeenFirstLinkerInput = false; // Add extra linker input arguments which are not treated as inputs // (constructed via -Xarch_). @@ -248,6 +266,14 @@ void tools::AddLinkerInputs(const ToolChain &TC, const InputInfoList &Inputs, if (II.isNothing()) continue; + // Add Fortan "main" before the first linker input + if (!SeenFirstLinkerInput) { + if (needFortranMain(D, Args)) { + CmdArgs.push_back("-lflangmain"); + } + SeenFirstLinkerInput = true; + } + // Otherwise, this is a linker input argument. const Arg &A = II.getInputArg(); @@ -273,6 +299,15 @@ void tools::AddLinkerInputs(const ToolChain &TC, const InputInfoList &Inputs, A.renderAsInput(Args, CmdArgs); } } + + if (!SeenFirstLinkerInput && needFortranMain(D, Args)) { + CmdArgs.push_back("-lflangmain"); + } + + // Claim "no Fortran main" arguments + for (auto Arg : Args.filtered(options::OPT_no_fortran_main, options::OPT_Mnomain)) { + Arg->claim(); + } } void tools::addLinkerCompressDebugSectionsOption( diff --git a/clang/lib/Driver/ToolChains/CommonArgs.h b/clang/lib/Driver/ToolChains/CommonArgs.h index 8e62af70ff7f..82ad2f387f08 100644 --- a/clang/lib/Driver/ToolChains/CommonArgs.h +++ b/clang/lib/Driver/ToolChains/CommonArgs.h @@ -20,6 +20,8 @@ namespace clang { namespace driver { namespace tools { +bool needFortranLibs(const Driver &D, const llvm::opt::ArgList &Args); + void addPathIfExists(const Driver &D, const Twine &Path, ToolChain::path_list &Paths); diff --git a/clang/lib/Driver/ToolChains/Cuda.cpp b/clang/lib/Driver/ToolChains/Cuda.cpp index 7ad990dda467..997b1e9ce7fc 100644 --- a/clang/lib/Driver/ToolChains/Cuda.cpp +++ b/clang/lib/Driver/ToolChains/Cuda.cpp @@ -919,3 +919,36 @@ VersionTuple CudaToolChain::computeMSVCVersion(const Driver *D, const ArgList &Args) const { return HostTC.computeMSVCVersion(D, Args); } + +static void AddFlangSysIncludeArg(const ArgList &DriverArgs, + ArgStringList &Flang1Args, + ToolChain::path_list IncludePathList) { + std::string ArgValue; // Path argument value + + // Make up argument value consisting of paths separated by colons + bool first = true; + for (auto P : IncludePathList) { + if (first) { + first = false; + } else { + ArgValue += ":"; + } + ArgValue += P; + } + + // Add the argument + Flang1Args.push_back("-stdinc"); + Flang1Args.push_back(DriverArgs.MakeArgString(ArgValue)); +} + +void CudaToolChain::AddFlangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs, + llvm::opt::ArgStringList &Flang1Args) const { + path_list IncludePathList; + const Driver &D = getDriver(); + if (DriverArgs.hasArg(options::OPT_nostdinc)) + return; + SmallString<128> P(D.InstalledDir); + llvm::sys::path::append(P, "../include"); + IncludePathList.push_back(P.c_str()); + AddFlangSysIncludeArg(DriverArgs, Flang1Args, IncludePathList); +} diff --git a/clang/lib/Driver/ToolChains/Cuda.h b/clang/lib/Driver/ToolChains/Cuda.h index 809a25227ac4..d860c7a433f6 100644 --- a/clang/lib/Driver/ToolChains/Cuda.h +++ b/clang/lib/Driver/ToolChains/Cuda.h @@ -198,6 +198,9 @@ public: const ToolChain &HostTC; CudaInstallationDetector CudaInstallation; + void + AddFlangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs, + llvm::opt::ArgStringList &Flang1Args) const override; protected: Tool *buildAssembler() const override; // ptxas Tool *buildLinker() const override; // fatbinary (ok, not really a linker) diff --git a/clang/lib/Driver/ToolChains/Gnu.cpp b/clang/lib/Driver/ToolChains/Gnu.cpp index 665cdc3132fb..1c0800fdbc77 100644 --- a/clang/lib/Driver/ToolChains/Gnu.cpp +++ b/clang/lib/Driver/ToolChains/Gnu.cpp @@ -567,6 +567,16 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA, // The profile runtime also needs access to system libraries. getToolChain().addProfileRTLibs(Args, CmdArgs); + // Add Fortran runtime libraries + if (needFortranLibs(D, Args)) { + ToolChain.AddFortranStdlibLibArgs(Args, CmdArgs); + } else { + // Claim "no Flang libraries" arguments if any + for (auto Arg : Args.filtered(options::OPT_noFlangLibs)) { + Arg->claim(); + } + } + if (D.CCCIsCXX() && !Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs, options::OPT_r)) { diff --git a/clang/lib/Driver/ToolChains/Linux.cpp b/clang/lib/Driver/ToolChains/Linux.cpp index ceb1a982c3a4..23838ee992b2 100644 --- a/clang/lib/Driver/ToolChains/Linux.cpp +++ b/clang/lib/Driver/ToolChains/Linux.cpp @@ -566,6 +566,194 @@ std::string Linux::getDynamicLinker(const ArgList &Args) const { return "/" + LibDir + "/" + Loader; } +/// Convert path list to Fortran frontend argument +static void AddFlangSysIncludeArg(const ArgList &DriverArgs, + ArgStringList &Flang1Args, + ToolChain::path_list IncludePathList) { + std::string ArgValue; // Path argument value + + // Make up argument value consisting of paths separated by colons + bool first = true; + for (auto P : IncludePathList) { + if (first) { + first = false; + } else { + ArgValue += ":"; + } + ArgValue += P; + } + + // Add the argument + Flang1Args.push_back("-stdinc"); + Flang1Args.push_back(DriverArgs.MakeArgString(ArgValue)); +} + +void Linux::AddFlangSystemIncludeArgs(const ArgList &DriverArgs, + ArgStringList &Flang1Args) const { + path_list IncludePathList; + const Driver &D = getDriver(); + std::string SysRoot = computeSysRoot(); + + if (DriverArgs.hasArg(options::OPT_nostdinc)) + return; + + { + SmallString<128> P(D.InstalledDir); + llvm::sys::path::append(P, "../include"); + IncludePathList.push_back(P.c_str()); + } + + if (!DriverArgs.hasArg(options::OPT_nostdlibinc)) + IncludePathList.push_back(SysRoot + "/usr/local/include"); + + if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) { + SmallString<128> P(D.ResourceDir); + llvm::sys::path::append(P, "include"); + IncludePathList.push_back(P.c_str()); + } + + if (DriverArgs.hasArg(options::OPT_nostdlibinc)) { + AddFlangSysIncludeArg(DriverArgs, Flang1Args, IncludePathList); + return; + } + + // Check for configure-time C include directories. + StringRef CIncludeDirs(C_INCLUDE_DIRS); + if (CIncludeDirs != "") { + SmallVector dirs; + CIncludeDirs.split(dirs, ":"); + for (StringRef dir : dirs) { + StringRef Prefix = + llvm::sys::path::is_absolute(dir) ? StringRef(SysRoot) : ""; + IncludePathList.push_back(Prefix.str() + dir.str()); + } + AddFlangSysIncludeArg(DriverArgs, Flang1Args, IncludePathList); + return; + } + + // Lacking those, try to detect the correct set of system includes for the + // target triple. + + // Add include directories specific to the selected multilib set and multilib. + if (GCCInstallation.isValid()) { + const auto &Callback = Multilibs.includeDirsCallback(); + if (Callback) { + for (const auto &Path : Callback(GCCInstallation.getMultilib())) + addExternCSystemIncludeIfExists( + DriverArgs, Flang1Args, GCCInstallation.getInstallPath() + Path); + } + } + + // Implement generic Debian multiarch support. + const StringRef X86_64MultiarchIncludeDirs[] = { + "/usr/include/x86_64-linux-gnu", + + // FIXME: These are older forms of multiarch. It's not clear that they're + // in use in any released version of Debian, so we should consider + // removing them. + "/usr/include/i686-linux-gnu/64", "/usr/include/i486-linux-gnu/64"}; + const StringRef X86MultiarchIncludeDirs[] = { + "/usr/include/i386-linux-gnu", + + // FIXME: These are older forms of multiarch. It's not clear that they're + // in use in any released version of Debian, so we should consider + // removing them. + "/usr/include/x86_64-linux-gnu/32", "/usr/include/i686-linux-gnu", + "/usr/include/i486-linux-gnu"}; + const StringRef AArch64MultiarchIncludeDirs[] = { + "/usr/include/aarch64-linux-gnu"}; + const StringRef ARMMultiarchIncludeDirs[] = { + "/usr/include/arm-linux-gnueabi"}; + const StringRef ARMHFMultiarchIncludeDirs[] = { + "/usr/include/arm-linux-gnueabihf"}; + const StringRef MIPSMultiarchIncludeDirs[] = {"/usr/include/mips-linux-gnu"}; + const StringRef MIPSELMultiarchIncludeDirs[] = { + "/usr/include/mipsel-linux-gnu"}; + const StringRef MIPS64MultiarchIncludeDirs[] = { + "/usr/include/mips64-linux-gnu", "/usr/include/mips64-linux-gnuabi64"}; + const StringRef MIPS64ELMultiarchIncludeDirs[] = { + "/usr/include/mips64el-linux-gnu", + "/usr/include/mips64el-linux-gnuabi64"}; + const StringRef PPCMultiarchIncludeDirs[] = { + "/usr/include/powerpc-linux-gnu"}; + const StringRef PPC64MultiarchIncludeDirs[] = { + "/usr/include/powerpc64-linux-gnu"}; + const StringRef PPC64LEMultiarchIncludeDirs[] = { + "/usr/include/powerpc64le-linux-gnu"}; + const StringRef SparcMultiarchIncludeDirs[] = { + "/usr/include/sparc-linux-gnu"}; + const StringRef Sparc64MultiarchIncludeDirs[] = { + "/usr/include/sparc64-linux-gnu"}; + ArrayRef MultiarchIncludeDirs; + switch (getTriple().getArch()) { + case llvm::Triple::x86_64: + MultiarchIncludeDirs = X86_64MultiarchIncludeDirs; + break; + case llvm::Triple::x86: + MultiarchIncludeDirs = X86MultiarchIncludeDirs; + break; + case llvm::Triple::aarch64: + case llvm::Triple::aarch64_be: + MultiarchIncludeDirs = AArch64MultiarchIncludeDirs; + break; + case llvm::Triple::arm: + if (getTriple().getEnvironment() == llvm::Triple::GNUEABIHF) + MultiarchIncludeDirs = ARMHFMultiarchIncludeDirs; + else + MultiarchIncludeDirs = ARMMultiarchIncludeDirs; + break; + case llvm::Triple::mips: + MultiarchIncludeDirs = MIPSMultiarchIncludeDirs; + break; + case llvm::Triple::mipsel: + MultiarchIncludeDirs = MIPSELMultiarchIncludeDirs; + break; + case llvm::Triple::mips64: + MultiarchIncludeDirs = MIPS64MultiarchIncludeDirs; + break; + case llvm::Triple::mips64el: + MultiarchIncludeDirs = MIPS64ELMultiarchIncludeDirs; + break; + case llvm::Triple::ppc: + MultiarchIncludeDirs = PPCMultiarchIncludeDirs; + break; + case llvm::Triple::ppc64: + MultiarchIncludeDirs = PPC64MultiarchIncludeDirs; + break; + case llvm::Triple::ppc64le: + MultiarchIncludeDirs = PPC64LEMultiarchIncludeDirs; + break; + case llvm::Triple::sparc: + MultiarchIncludeDirs = SparcMultiarchIncludeDirs; + break; + case llvm::Triple::sparcv9: + MultiarchIncludeDirs = Sparc64MultiarchIncludeDirs; + break; + default: + break; + } + for (StringRef Dir : MultiarchIncludeDirs) { + if (llvm::sys::fs::exists(SysRoot + Dir)) { + IncludePathList.push_back(SysRoot + Dir.str()); + break; + } + } + + if (getTriple().getOS() == llvm::Triple::RTEMS) { + AddFlangSysIncludeArg(DriverArgs, Flang1Args, IncludePathList); + return; + } + + // Add an include of '/include' directly. This isn't provided by default by + // system GCCs, but is often used with cross-compiling GCCs, and harmless to + // add even when Clang is acting as-if it were a system compiler. + IncludePathList.push_back(SysRoot + "/include"); + + IncludePathList.push_back(SysRoot + "/usr/include"); + + AddFlangSysIncludeArg(DriverArgs, Flang1Args, IncludePathList); +} + void Linux::AddClangSystemIncludeArgs(const ArgList &DriverArgs, ArgStringList &CC1Args) const { const Driver &D = getDriver(); diff --git a/clang/lib/Driver/ToolChains/Linux.h b/clang/lib/Driver/ToolChains/Linux.h index 188cb1f09788..58e8f0358305 100644 --- a/clang/lib/Driver/ToolChains/Linux.h +++ b/clang/lib/Driver/ToolChains/Linux.h @@ -28,6 +28,9 @@ public: StringRef SysRoot) const override; void + AddFlangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs, + llvm::opt::ArgStringList &Flang1Args) const override; + void AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args) const override; void addLibStdCxxIncludePaths( diff --git a/clang/lib/Driver/Types.cpp b/clang/lib/Driver/Types.cpp old mode 100644 new mode 100755 index 66da6fe97059..e147666d9663 --- a/clang/lib/Driver/Types.cpp +++ b/clang/lib/Driver/Types.cpp @@ -55,9 +55,11 @@ const char *types::getTypeName(ID Id) { types::ID types::getPreprocessedType(ID Id) { ID PPT = getInfo(Id).PreprocessedType; +#ifndef ENABLE_CLASSIC_FLANG assert((getInfo(Id).Phases.contains(phases::Preprocess) != (PPT == TY_INVALID)) && "Unexpected Preprocess Type."); +#endif return PPT; } @@ -134,6 +136,10 @@ bool types::isAcceptedByClang(ID Id) { case TY_Asm: case TY_C: case TY_PP_C: case TY_CL: case TY_CLCXX: +#ifdef ENABLE_CLASSIC_FLANG + case TY_F_FreeForm: case TY_PP_F_FreeForm: + case TY_F_FixedForm: case TY_PP_F_FixedForm: +#endif case TY_CUDA: case TY_PP_CUDA: case TY_CUDA_DEVICE: case TY_HIP: @@ -164,8 +170,15 @@ bool types::isAcceptedByFlang(ID Id) { default: return false; +#ifdef ENABLE_CLASSIC_FLANG + case TY_F_FreeForm: + case TY_PP_F_FreeForm: + case TY_F_FixedForm: + case TY_PP_F_FixedForm: +#else case TY_Fortran: case TY_PP_Fortran: +#endif return true; case TY_LLVM_IR: case TY_LLVM_BC: @@ -286,6 +299,22 @@ bool types::isHIP(ID Id) { } } +#ifdef ENABLE_CLASSIC_FLANG +bool types::isFreeFormFortran(ID Id) { + if (!isAcceptedByFlang(Id)) + return false; + + return (Id == TY_F_FreeForm || Id == TY_PP_F_FreeForm); +} + +bool types::isFixedFormFortran(ID Id) { + if (!isAcceptedByFlang(Id)) + return false; + + return (Id == TY_F_FixedForm || Id == TY_PP_F_FixedForm); +} +#endif + bool types::isSrcFile(ID Id) { return Id != TY_Object && getPreprocessedType(Id) != TY_INVALID; } @@ -294,8 +323,13 @@ types::ID types::lookupTypeForExtension(llvm::StringRef Ext) { return llvm::StringSwitch(Ext) .Case("c", TY_C) .Case("C", TY_CXX) +#ifdef ENABLE_CLASSIC_FLANG + .Case("F", TY_F_FixedForm) + .Case("f", TY_PP_F_FixedForm) +#else .Case("F", TY_Fortran) .Case("f", TY_PP_Fortran) +#endif .Case("h", TY_CHeader) .Case("H", TY_CXXHeader) .Case("i", TY_PP_C) @@ -329,6 +363,20 @@ types::ID types::lookupTypeForExtension(llvm::StringRef Ext) { .Case("cui", TY_PP_CUDA) .Case("cxx", TY_CXX) .Case("CXX", TY_CXX) +#ifdef ENABLE_CLASSIC_FLANG + .Case("for", TY_PP_F_FixedForm) + .Case("FOR", TY_PP_F_FixedForm) + .Case("fpp", TY_F_FixedForm) + .Case("FPP", TY_F_FixedForm) + .Case("f90", TY_PP_F_FreeForm) + .Case("f95", TY_PP_F_FreeForm) + .Case("f03", TY_PP_F_FreeForm) + .Case("f08", TY_PP_F_FreeForm) + .Case("F90", TY_F_FreeForm) + .Case("F95", TY_F_FreeForm) + .Case("F03", TY_F_FreeForm) + .Case("F08", TY_F_FreeForm) +#else .Case("F90", TY_Fortran) .Case("f90", TY_PP_Fortran) .Case("F95", TY_Fortran) @@ -337,6 +385,7 @@ types::ID types::lookupTypeForExtension(llvm::StringRef Ext) { .Case("FOR", TY_PP_Fortran) .Case("fpp", TY_Fortran) .Case("FPP", TY_Fortran) +#endif .Case("gch", TY_PCH) .Case("hip", TY_HIP) .Case("hpp", TY_CXXHeader) diff --git a/clang/lib/Frontend/InitPreprocessor.cpp b/clang/lib/Frontend/InitPreprocessor.cpp index 20bfbf144a30..db02d65a1d9d 100644 --- a/clang/lib/Frontend/InitPreprocessor.cpp +++ b/clang/lib/Frontend/InitPreprocessor.cpp @@ -160,26 +160,6 @@ static void DefineFloatMacros(MacroBuilder &Builder, StringRef Prefix, Builder.defineMacro(DefPrefix + "MIN__", Twine(Min)+Ext); } - -/// DefineTypeSize - Emit a macro to the predefines buffer that declares a macro -/// named MacroName with the max value for a type with width 'TypeWidth' a -/// signedness of 'isSigned' and with a value suffix of 'ValSuffix' (e.g. LL). -static void DefineTypeSize(const Twine &MacroName, unsigned TypeWidth, - StringRef ValSuffix, bool isSigned, - MacroBuilder &Builder) { - llvm::APInt MaxVal = isSigned ? llvm::APInt::getSignedMaxValue(TypeWidth) - : llvm::APInt::getMaxValue(TypeWidth); - Builder.defineMacro(MacroName, toString(MaxVal, 10, isSigned) + ValSuffix); -} - -/// DefineTypeSize - An overloaded helper that uses TargetInfo to determine -/// the width, suffix, and signedness of the given type -static void DefineTypeSize(const Twine &MacroName, TargetInfo::IntType Ty, - const TargetInfo &TI, MacroBuilder &Builder) { - DefineTypeSize(MacroName, TI.getTypeWidth(Ty), TI.getTypeConstantSuffix(Ty), - TI.isTypeSigned(Ty), Builder); -} - static void DefineFmt(const Twine &Prefix, TargetInfo::IntType Ty, const TargetInfo &TI, MacroBuilder &Builder) { bool IsSigned = TI.isTypeSigned(Ty); diff --git a/clang/test/Driver/autocomplete.c b/clang/test/Driver/autocomplete.c index 59055efac2ce..1cb2cebeeac8 100644 --- a/clang/test/Driver/autocomplete.c +++ b/clang/test/Driver/autocomplete.c @@ -84,7 +84,7 @@ // FVECLIBALL-NEXT: libmvec // FVECLIBALL-NEXT: MASSV // FVECLIBALL-NEXT: none -// FVECLIBALL-NEXT: SVML +// FVECLIBALL: SVML // RUN: %clang --autocomplete=-fshow-overloads= | FileCheck %s -check-prefix=FSOVERALL // FSOVERALL: all // FSOVERALL-NEXT: best diff --git a/clang/test/Driver/flang/classic_flang.f95 b/clang/test/Driver/flang/classic_flang.f95 new file mode 100644 index 000000000000..5d3098786905 --- /dev/null +++ b/clang/test/Driver/flang/classic_flang.f95 @@ -0,0 +1,28 @@ +! Check that the driver can invoke flang1 and flang2 to compile Fortran with +! --driver-mode=flang (default when the file extension is .f95). + +! REQUIRES: classic_flang + +! RUN: %clang -target x86_64-unknown-linux-gnu -integrated-as -c %s -### 2>&1 \ +! RUN: | FileCheck --check-prefix=CHECK-OBJECT %s +! CHECK-OBJECT: flang1 +! CHECK-OBJECT: flang2 +! CHECK-OBJECT-SAME: "-asm" [[LLFILE:.*.ll]] +! CHECK-OBJECT-NOT: cc1as +! CHECK-OBJECT: clang +! CHECK-OBJECT-SAME: -cc1 +! CHECK-OBJECT-SAME: "-o" "classic_flang.o" +! CHECK-OBJECT-SAME: "-x" "ir" +! CHECK-OBJECT-SAME: [[LLFILE]] + +! RUN: %clang -target x86_64-unknown-linux-gnu -integrated-as -S %s -### 2>&1 \ +! RUN: | FileCheck --check-prefix=CHECK-ASM %s +! CHECK-ASM: flang1 +! CHECK-ASM: flang2 +! CHECK-ASM-SAME: "-asm" [[LLFILE:.*.ll]] +! CHECK-ASM-NOT: cc1as +! CHECK-ASM: clang +! CHECK-ASM-SAME: -cc1 +! CHECK-ASM-SAME: "-o" "classic_flang.s" +! CHECK-ASM-SAME: "-x" "ir" +! CHECK-ASM-SAME: [[LLFILE]] diff --git a/clang/test/Driver/flang/flang.f90 b/clang/test/Driver/flang/flang.f90 index 9b16f233b231..5ff05ccccdce 100644 --- a/clang/test/Driver/flang/flang.f90 +++ b/clang/test/Driver/flang/flang.f90 @@ -1,5 +1,7 @@ ! Check that flang -fc1 is invoked when in --driver-mode=flang. +! UNSUPPORTED: classic_flang + ! This is a copy of flang_ucase.F90 because the driver has logic in it which ! differentiates between F90 and f90 files. Flang will not treat these files ! differently. diff --git a/clang/test/Driver/flang/flang_ucase.F90 b/clang/test/Driver/flang/flang_ucase.F90 index 113ef75f45b8..93a4d792e217 100644 --- a/clang/test/Driver/flang/flang_ucase.F90 +++ b/clang/test/Driver/flang/flang_ucase.F90 @@ -1,5 +1,7 @@ ! Check that flang -fc1 is invoked when in --driver-mode=flang. +! UNSUPPORTED: classic_flang + ! This is a copy of flang.f90 because the driver has logic in it which ! differentiates between F90 and f90 files. Flang will not treat these files ! differently. diff --git a/clang/test/Driver/flang/multiple-inputs-mixed.f90 b/clang/test/Driver/flang/multiple-inputs-mixed.f90 index 2395dbecf1fe..8f3918f7cb21 100644 --- a/clang/test/Driver/flang/multiple-inputs-mixed.f90 +++ b/clang/test/Driver/flang/multiple-inputs-mixed.f90 @@ -1,5 +1,7 @@ ! Check that flang can handle mixed C and fortran inputs. +! UNSUPPORTED: classic_flang + ! RUN: %clang --driver-mode=flang -### -fsyntax-only %S/Inputs/one.f90 %S/Inputs/other.c 2>&1 | FileCheck --check-prefixes=CHECK-SYNTAX-ONLY %s ! CHECK-SYNTAX-ONLY-LABEL: "{{[^"]*}}flang-new{{[^"/]*}}" "-fc1" ! CHECK-SYNTAX-ONLY: "{{[^"]*}}/Inputs/one.f90" diff --git a/clang/test/Driver/flang/multiple-inputs.f90 b/clang/test/Driver/flang/multiple-inputs.f90 index f6ee60e48fef..59b7e1f21227 100644 --- a/clang/test/Driver/flang/multiple-inputs.f90 +++ b/clang/test/Driver/flang/multiple-inputs.f90 @@ -1,5 +1,7 @@ ! Check that flang driver can handle multiple inputs at once. +! UNSUPPORTED: classic_flang + ! RUN: %clang --driver-mode=flang -### -fsyntax-only %S/Inputs/one.f90 %S/Inputs/two.f90 2>&1 | FileCheck --check-prefixes=CHECK-SYNTAX-ONLY %s ! CHECK-SYNTAX-ONLY-LABEL: "{{[^"]*}}flang-new" "-fc1" ! CHECK-SYNTAX-ONLY: "{{[^"]*}}/Inputs/one.f90" diff --git a/clang/test/Driver/fortran.f95 b/clang/test/Driver/fortran.f95 index db3ff2da17e8..e364180a1f9c 100644 --- a/clang/test/Driver/fortran.f95 +++ b/clang/test/Driver/fortran.f95 @@ -1,6 +1,8 @@ ! Check that the clang driver can invoke gcc to compile Fortran when in ! --driver-mode=clang. This is legacy behaviour - see also --driver-mode=flang. +! UNSUPPORTED: classic_flang + ! RUN: %clang -target x86_64-unknown-linux-gnu -integrated-as -c %s -### 2>&1 \ ! RUN: | FileCheck --check-prefix=CHECK-OBJECT %s ! CHECK-OBJECT: gcc diff --git a/clang/test/Driver/gfortran.f90 b/clang/test/Driver/gfortran.f90 index c985428650ec..1276703b1f6e 100644 --- a/clang/test/Driver/gfortran.f90 +++ b/clang/test/Driver/gfortran.f90 @@ -1,4 +1,5 @@ ! XFAIL: * +! UNSUPPORTED: classic_flang ! Test that Clang can forward all of the flags which are documented as ! being supported by gfortran to GCC when falling back to GCC for ! a fortran input file. diff --git a/clang/test/lit.cfg.py b/clang/test/lit.cfg.py index d95ea5d2da19..702121b68645 100644 --- a/clang/test/lit.cfg.py +++ b/clang/test/lit.cfg.py @@ -274,3 +274,6 @@ if 'AIXTHREAD_STK' in os.environ: config.environment['AIXTHREAD_STK'] = os.environ['AIXTHREAD_STK'] elif platform.system() == 'AIX': config.environment['AIXTHREAD_STK'] = '4194304' + +if config.use_classic_flang: + config.available_features.add("classic_flang") diff --git a/clang/test/lit.site.cfg.py.in b/clang/test/lit.site.cfg.py.in index 8a9849fe4549..f9abbba41236 100644 --- a/clang/test/lit.site.cfg.py.in +++ b/clang/test/lit.site.cfg.py.in @@ -37,6 +37,7 @@ config.use_z3_solver = lit_config.params.get('USE_Z3_SOLVER', "@USE_Z3_SOLVER@") config.has_plugins = @CLANG_PLUGIN_SUPPORT@ config.clang_vendor_uti = "@CLANG_VENDOR_UTI@" config.llvm_external_lit = path(r"@LLVM_EXTERNAL_LIT@") +config.use_classic_flang = @LLVM_ENABLE_CLASSIC_FLANG@ import lit.llvm lit.llvm.initialize(lit_config, config) diff --git a/clang/tools/clang-offload-bundler/ClangOffloadBundler.cpp b/clang/tools/clang-offload-bundler/ClangOffloadBundler.cpp index 77370ed8342d..e8cc37884e74 100644 --- a/clang/tools/clang-offload-bundler/ClangOffloadBundler.cpp +++ b/clang/tools/clang-offload-bundler/ClangOffloadBundler.cpp @@ -898,6 +898,8 @@ CreateFileHandler(MemoryBuffer &FirstInput) { return std::make_unique(/*Comment=*/"#"); if (FilesType == "ll") return std::make_unique(/*Comment=*/";"); + if (FilesType == "f95") + return std::make_unique(/*Comment=*/"!"); if (FilesType == "bc") return std::make_unique(); if (FilesType == "s") diff --git a/clang/tools/driver/CMakeLists.txt b/clang/tools/driver/CMakeLists.txt index d05b71db13f2..0727c7ff7300 100644 --- a/clang/tools/driver/CMakeLists.txt +++ b/clang/tools/driver/CMakeLists.txt @@ -58,7 +58,7 @@ endif() add_dependencies(clang clang-resource-headers) if(NOT CLANG_LINKS_TO_CREATE) - set(CLANG_LINKS_TO_CREATE clang++ clang-cl clang-cpp) + set(CLANG_LINKS_TO_CREATE clang++ clang-cl clang-cpp flang) endif() foreach(link ${CLANG_LINKS_TO_CREATE}) diff --git a/llvm/cmake/modules/HandleLLVMOptions.cmake b/llvm/cmake/modules/HandleLLVMOptions.cmake index 0fca934be9cf..a3d93b077040 100644 --- a/llvm/cmake/modules/HandleLLVMOptions.cmake +++ b/llvm/cmake/modules/HandleLLVMOptions.cmake @@ -85,6 +85,14 @@ if( LLVM_ENABLE_ASSERTIONS ) endif() endif() +option(LLVM_ENABLE_CLASSIC_FLANG "Build support for classic Flang instead of the new built-in Flang" OFF) +if(LLVM_ENABLE_CLASSIC_FLANG) + set(LLVM_ENABLE_CLASSIC_FLANG 1) + add_definitions( -DENABLE_CLASSIC_FLANG ) +else() + set(LLVM_ENABLE_CLASSIC_FLANG 0) +endif() + if(LLVM_ENABLE_EXPENSIVE_CHECKS) add_definitions(-DEXPENSIVE_CHECKS) diff --git a/llvm/include/llvm-c/DebugInfo.h b/llvm/include/llvm-c/DebugInfo.h index 8554a0199873..bcce786654ef 100644 --- a/llvm/include/llvm-c/DebugInfo.h +++ b/llvm/include/llvm-c/DebugInfo.h @@ -1137,7 +1137,8 @@ LLVMMetadataRef LLVMDIBuilderCreateGlobalVariableExpression( LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name, size_t NameLen, const char *Linkage, size_t LinkLen, LLVMMetadataRef File, unsigned LineNo, LLVMMetadataRef Ty, LLVMBool LocalToUnit, - LLVMMetadataRef Expr, LLVMMetadataRef Decl, uint32_t AlignInBits); + LLVMMetadataRef Expr, LLVMMetadataRef Decl, LLVMDIFlags Flags, + uint32_t AlignInBits); /** * Retrieves the \c DIVariable associated with this global variable expression. @@ -1229,7 +1230,7 @@ LLVMMetadataRef LLVMDIBuilderCreateTempGlobalVariableFwdDecl( LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name, size_t NameLen, const char *Linkage, size_t LnkLen, LLVMMetadataRef File, unsigned LineNo, LLVMMetadataRef Ty, LLVMBool LocalToUnit, - LLVMMetadataRef Decl, uint32_t AlignInBits); + LLVMMetadataRef Decl, LLVMDIFlags Flags, uint32_t AlignInBits); /** * Insert a new llvm.dbg.declare intrinsic call before the given instruction. diff --git a/llvm/include/llvm/Analysis/TargetLibraryInfo.h b/llvm/include/llvm/Analysis/TargetLibraryInfo.h index 7bfda0124de7..bf642394b806 100644 --- a/llvm/include/llvm/Analysis/TargetLibraryInfo.h +++ b/llvm/include/llvm/Analysis/TargetLibraryInfo.h @@ -93,6 +93,7 @@ public: DarwinLibSystemM, // Use Darwin's libsystem_m. LIBMVEC_X86, // GLIBC Vector Math library. MASSV, // IBM MASS vector library. + PGMATH, // PGI math library. SVML // Intel short vector math library. }; diff --git a/llvm/include/llvm/IR/DIBuilder.h b/llvm/include/llvm/IR/DIBuilder.h index 9afa715b650c..15600635d28e 100644 --- a/llvm/include/llvm/IR/DIBuilder.h +++ b/llvm/include/llvm/IR/DIBuilder.h @@ -675,15 +675,17 @@ namespace llvm { DIScope *Context, StringRef Name, StringRef LinkageName, DIFile *File, unsigned LineNo, DIType *Ty, bool IsLocalToUnit, bool isDefined = true, DIExpression *Expr = nullptr, MDNode *Decl = nullptr, - MDTuple *TemplateParams = nullptr, uint32_t AlignInBits = 0, + MDTuple *TemplateParams = nullptr, + DINode::DIFlags Flags = DINode::FlagZero, uint32_t AlignInBits = 0, DINodeArray Annotations = nullptr); /// Identical to createGlobalVariable /// except that the resulting DbgNode is temporary and meant to be RAUWed. DIGlobalVariable *createTempGlobalVariableFwdDecl( DIScope *Context, StringRef Name, StringRef LinkageName, DIFile *File, - unsigned LineNo, DIType *Ty, bool IsLocalToUnit, MDNode *Decl = nullptr, - MDTuple *TemplateParams= nullptr, uint32_t AlignInBits = 0); + unsigned LineNo, DIType *Ty, bool isLocalToUnit, MDNode *Decl = nullptr, + MDTuple *TemplateParams = nullptr, + DINode::DIFlags Flags = DINode::FlagZero, uint32_t AlignInBits = 0); /// Create a new descriptor for an auto variable. This is a local variable /// that is not a subprogram parameter. @@ -814,6 +816,17 @@ namespace llvm { StringRef Name, DIFile *File, unsigned LineNo); + /// Create common block entry for a Fortran common block + /// \param Scope Scope of this common block + /// \param Name The name of this common block + /// \param File The file this common block is defined + /// \param LineNo Line number + /// \param VarList List of variables that a located in common block + /// \param AlignInBits Common block alignment + DICommonBlock *createCommonBlock(DIScope *Scope, DIGlobalVariable *decl, + StringRef Name, DIFile *File, + unsigned LineNo, uint32_t AlignInBits = 0); + /// This creates new descriptor for a namespace with the specified /// parent scope. /// \param Scope Namespace scope diff --git a/llvm/include/llvm/IR/DebugInfoMetadata.h b/llvm/include/llvm/IR/DebugInfoMetadata.h index db1d031a062d..e7bb525736dc 100644 --- a/llvm/include/llvm/IR/DebugInfoMetadata.h +++ b/llvm/include/llvm/IR/DebugInfoMetadata.h @@ -2917,12 +2917,14 @@ class DIGlobalVariable : public DIVariable { bool IsLocalToUnit; bool IsDefinition; + DIFlags Flags; DIGlobalVariable(LLVMContext &C, StorageType Storage, unsigned Line, - bool IsLocalToUnit, bool IsDefinition, uint32_t AlignInBits, - ArrayRef Ops) + bool IsLocalToUnit, bool IsDefinition, DIFlags Flags, + uint32_t AlignInBits, ArrayRef Ops) : DIVariable(C, DIGlobalVariableKind, Storage, Line, Ops, AlignInBits), - IsLocalToUnit(IsLocalToUnit), IsDefinition(IsDefinition) {} + IsLocalToUnit(IsLocalToUnit), IsDefinition(IsDefinition), + Flags(Flags) {} ~DIGlobalVariable() = default; static DIGlobalVariable * @@ -2930,12 +2932,12 @@ class DIGlobalVariable : public DIVariable { StringRef LinkageName, DIFile *File, unsigned Line, DIType *Type, bool IsLocalToUnit, bool IsDefinition, DIDerivedType *StaticDataMemberDeclaration, MDTuple *TemplateParams, - uint32_t AlignInBits, DINodeArray Annotations, StorageType Storage, - bool ShouldCreate = true) { + DIFlags Flags, uint32_t AlignInBits, DINodeArray Annotations, + StorageType Storage, bool ShouldCreate = true) { return getImpl(Context, Scope, getCanonicalMDString(Context, Name), getCanonicalMDString(Context, LinkageName), File, Line, Type, IsLocalToUnit, IsDefinition, StaticDataMemberDeclaration, - cast_or_null(TemplateParams), AlignInBits, + cast_or_null(TemplateParams), Flags, AlignInBits, Annotations.get(), Storage, ShouldCreate); } static DIGlobalVariable * @@ -2943,14 +2945,14 @@ class DIGlobalVariable : public DIVariable { MDString *LinkageName, Metadata *File, unsigned Line, Metadata *Type, bool IsLocalToUnit, bool IsDefinition, Metadata *StaticDataMemberDeclaration, Metadata *TemplateParams, - uint32_t AlignInBits, Metadata *Annotations, StorageType Storage, - bool ShouldCreate = true); + DIFlags Flags, uint32_t AlignInBits, Metadata *Annotations, + StorageType Storage, bool ShouldCreate = true); TempDIGlobalVariable cloneImpl() const { return getTemporary(getContext(), getScope(), getName(), getLinkageName(), getFile(), getLine(), getType(), isLocalToUnit(), isDefinition(), getStaticDataMemberDeclaration(), - getTemplateParams(), getAlignInBits(), + getTemplateParams(), getFlags(), getAlignInBits(), getAnnotations()); } @@ -2960,22 +2962,26 @@ public: (DIScope * Scope, StringRef Name, StringRef LinkageName, DIFile *File, unsigned Line, DIType *Type, bool IsLocalToUnit, bool IsDefinition, DIDerivedType *StaticDataMemberDeclaration, MDTuple *TemplateParams, - uint32_t AlignInBits, DINodeArray Annotations), + DIFlags Flags, uint32_t AlignInBits, DINodeArray Annotations), (Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, IsDefinition, - StaticDataMemberDeclaration, TemplateParams, AlignInBits, Annotations)) + StaticDataMemberDeclaration, TemplateParams, Flags, AlignInBits, + Annotations)) DEFINE_MDNODE_GET( DIGlobalVariable, (Metadata * Scope, MDString *Name, MDString *LinkageName, Metadata *File, unsigned Line, Metadata *Type, bool IsLocalToUnit, bool IsDefinition, Metadata *StaticDataMemberDeclaration, Metadata *TemplateParams, - uint32_t AlignInBits, Metadata *Annotations), + DIFlags Flags, uint32_t AlignInBits, Metadata *Annotations), (Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, IsDefinition, - StaticDataMemberDeclaration, TemplateParams, AlignInBits, Annotations)) + StaticDataMemberDeclaration, TemplateParams, Flags, AlignInBits, + Annotations)) TempDIGlobalVariable clone() const { return cloneImpl(); } bool isLocalToUnit() const { return IsLocalToUnit; } bool isDefinition() const { return IsDefinition; } + DIFlags getFlags() const { return Flags; } + bool isArtificial() const { return getFlags() & FlagArtificial; } StringRef getDisplayName() const { return getStringOperand(4); } StringRef getLinkageName() const { return getStringOperand(5); } DIDerivedType *getStaticDataMemberDeclaration() const { diff --git a/llvm/lib/Analysis/TargetLibraryInfo.cpp b/llvm/lib/Analysis/TargetLibraryInfo.cpp index 8ebdb65e88dc..845665b14809 100644 --- a/llvm/lib/Analysis/TargetLibraryInfo.cpp +++ b/llvm/lib/Analysis/TargetLibraryInfo.cpp @@ -31,7 +31,9 @@ static cl::opt ClVectorLibrary( clEnumValN(TargetLibraryInfoImpl::MASSV, "MASSV", "IBM MASS vector library"), clEnumValN(TargetLibraryInfoImpl::SVML, "SVML", - "Intel SVML library"))); + "Intel SVML library"), + clEnumValN(TargetLibraryInfoImpl::PGMATH, "PGMATH", + "PGI math library"))); StringLiteral const TargetLibraryInfoImpl::StandardNames[LibFunc::NumLibFuncs] = { @@ -1884,6 +1886,456 @@ void TargetLibraryInfoImpl::addVectorizableFunctionsFromVecLib( addVectorizableFunctions(VecFuncs); break; } + + // NOTE: All routines listed here are not available on all the architectures. + // Based on the size of vector registers available and the size of data, the + // vector width should be chosen correctly. + case PGMATH: { + const VecDesc VecFuncs[] = { + {"__fd_sin_1", "__fd_sin_2", FIXED(2)}, + {"__fd_sin_1", "__fd_sin_4", FIXED(4)}, + {"__fd_sin_1", "__fd_sin_8", FIXED(8)}, + + {"__fs_sin_1", "__fs_sin_4", FIXED(4)}, + {"__fs_sin_1", "__fs_sin_8", FIXED(8)}, + {"__fs_sin_1", "__fs_sin_16", FIXED(16)}, + + {"__pd_sin_1", "__pd_sin_2", FIXED(2)}, + {"__pd_sin_1", "__pd_sin_4", FIXED(4)}, + {"__pd_sin_1", "__pd_sin_8", FIXED(8)}, + + {"__ps_sin_1", "__ps_sin_4", FIXED(4)}, + {"__ps_sin_1", "__ps_sin_8", FIXED(8)}, + {"__ps_sin_1", "__ps_sin_16", FIXED(16)}, + + {"__rd_sin_1", "__rd_sin_2", FIXED(2)}, + {"__rd_sin_1", "__rd_sin_4", FIXED(4)}, + {"__rd_sin_1", "__rd_sin_8", FIXED(8)}, + + {"__rs_sin_1", "__rs_sin_4", FIXED(4)}, + {"__rs_sin_1", "__rs_sin_8", FIXED(8)}, + {"__rs_sin_1", "__rs_sin_16", FIXED(16)}, + + {"__fd_cos_1", "__fd_cos_2", FIXED(2)}, + {"__fd_cos_1", "__fd_cos_4", FIXED(4)}, + {"__fd_cos_1", "__fd_cos_8", FIXED(8)}, + + {"__fs_cos_1", "__fs_cos_4", FIXED(4)}, + {"__fs_cos_1", "__fs_cos_8", FIXED(8)}, + {"__fs_cos_1", "__fs_cos_16", FIXED(16)}, + + {"__pd_cos_1", "__pd_cos_2", FIXED(2)}, + {"__pd_cos_1", "__pd_cos_4", FIXED(4)}, + {"__pd_cos_1", "__pd_cos_8", FIXED(8)}, + + {"__ps_cos_1", "__ps_cos_4", FIXED(4)}, + {"__ps_cos_1", "__ps_cos_8", FIXED(8)}, + {"__ps_cos_1", "__ps_cos_16", FIXED(16)}, + + {"__rd_cos_1", "__rd_cos_2", FIXED(2)}, + {"__rd_cos_1", "__rd_cos_4", FIXED(4)}, + {"__rd_cos_1", "__rd_cos_8", FIXED(8)}, + + {"__rs_cos_1", "__rs_cos_4", FIXED(4)}, + {"__rs_cos_1", "__rs_cos_8", FIXED(8)}, + {"__rs_cos_1", "__rs_cos_16", FIXED(16)}, + + {"__fd_sincos_1", "__fd_sincos_2", FIXED(2)}, + {"__fd_sincos_1", "__fd_sincos_4", FIXED(4)}, + {"__fd_sincos_1", "__fd_sincos_8", FIXED(8)}, + + {"__fs_sincos_1", "__fs_sincos_4", FIXED(4)}, + {"__fs_sincos_1", "__fs_sincos_8", FIXED(8)}, + {"__fs_sincos_1", "__fs_sincos_16", FIXED(16)}, + + {"__pd_sincos_1", "__pd_sincos_2", FIXED(2)}, + {"__pd_sincos_1", "__pd_sincos_4", FIXED(4)}, + {"__pd_sincos_1", "__pd_sincos_8", FIXED(8)}, + + {"__ps_sincos_1", "__ps_sincos_4", FIXED(4)}, + {"__ps_sincos_1", "__ps_sincos_8", FIXED(8)}, + {"__ps_sincos_1", "__ps_sincos_16", FIXED(16)}, + + {"__rd_sincos_1", "__rd_sincos_2", FIXED(2)}, + {"__rd_sincos_1", "__rd_sincos_4", FIXED(4)}, + {"__rd_sincos_1", "__rd_sincos_8", FIXED(8)}, + + {"__rs_sincos_1", "__rs_sincos_4", FIXED(4)}, + {"__rs_sincos_1", "__rs_sincos_8", FIXED(8)}, + {"__rs_sincos_1", "__rs_sincos_16", FIXED(16)}, + + {"__fd_tan_1", "__fd_tan_2", FIXED(2)}, + {"__fd_tan_1", "__fd_tan_4", FIXED(4)}, + {"__fd_tan_1", "__fd_tan_8", FIXED(8)}, + + {"__fs_tan_1", "__fs_tan_4", FIXED(4)}, + {"__fs_tan_1", "__fs_tan_8", FIXED(8)}, + {"__fs_tan_1", "__fs_tan_16", FIXED(16)}, + + {"__pd_tan_1", "__pd_tan_2", FIXED(2)}, + {"__pd_tan_1", "__pd_tan_4", FIXED(4)}, + {"__pd_tan_1", "__pd_tan_8", FIXED(8)}, + + {"__ps_tan_1", "__ps_tan_4", FIXED(4)}, + {"__ps_tan_1", "__ps_tan_8", FIXED(8)}, + {"__ps_tan_1", "__ps_tan_16", FIXED(16)}, + + {"__rd_tan_1", "__rd_tan_2", FIXED(2)}, + {"__rd_tan_1", "__rd_tan_4", FIXED(4)}, + {"__rd_tan_1", "__rd_tan_8", FIXED(8)}, + + {"__rs_tan_1", "__rs_tan_4", FIXED(4)}, + {"__rs_tan_1", "__rs_tan_8", FIXED(8)}, + {"__rs_tan_1", "__rs_tan_16", FIXED(16)}, + + {"__fd_sinh_1", "__fd_sinh_2", FIXED(2)}, + {"__fd_sinh_1", "__fd_sinh_4", FIXED(4)}, + {"__fd_sinh_1", "__fd_sinh_8", FIXED(8)}, + + {"__fs_sinh_1", "__fs_sinh_4", FIXED(4)}, + {"__fs_sinh_1", "__fs_sinh_8", FIXED(8)}, + {"__fs_sinh_1", "__fs_sinh_16", FIXED(16)}, + + {"__pd_sinh_1", "__pd_sinh_2", FIXED(2)}, + {"__pd_sinh_1", "__pd_sinh_4", FIXED(4)}, + {"__pd_sinh_1", "__pd_sinh_8", FIXED(8)}, + + {"__ps_sinh_1", "__ps_sinh_4", FIXED(4)}, + {"__ps_sinh_1", "__ps_sinh_8", FIXED(8)}, + {"__ps_sinh_1", "__ps_sinh_16", FIXED(16)}, + + {"__rd_sinh_1", "__rd_sinh_2", FIXED(2)}, + {"__rd_sinh_1", "__rd_sinh_4", FIXED(4)}, + {"__rd_sinh_1", "__rd_sinh_8", FIXED(8)}, + + {"__rs_sinh_1", "__rs_sinh_4", FIXED(4)}, + {"__rs_sinh_1", "__rs_sinh_8", FIXED(8)}, + {"__rs_sinh_1", "__rs_sinh_16", FIXED(16)}, + + {"__fd_cosh_1", "__fd_cosh_2", FIXED(2)}, + {"__fd_cosh_1", "__fd_cosh_4", FIXED(4)}, + {"__fd_cosh_1", "__fd_cosh_8", FIXED(8)}, + + {"__fs_cosh_1", "__fs_cosh_4", FIXED(4)}, + {"__fs_cosh_1", "__fs_cosh_8", FIXED(8)}, + {"__fs_cosh_1", "__fs_cosh_16", FIXED(16)}, + + {"__pd_cosh_1", "__pd_cosh_2", FIXED(2)}, + {"__pd_cosh_1", "__pd_cosh_4", FIXED(4)}, + {"__pd_cosh_1", "__pd_cosh_8", FIXED(8)}, + + {"__ps_cosh_1", "__ps_cosh_4", FIXED(4)}, + {"__ps_cosh_1", "__ps_cosh_8", FIXED(8)}, + {"__ps_cosh_1", "__ps_cosh_16", FIXED(16)}, + + {"__rd_cosh_1", "__rd_cosh_2", FIXED(2)}, + {"__rd_cosh_1", "__rd_cosh_4", FIXED(4)}, + {"__rd_cosh_1", "__rd_cosh_8", FIXED(8)}, + + {"__rs_cosh_1", "__rs_cosh_4", FIXED(4)}, + {"__rs_cosh_1", "__rs_cosh_8", FIXED(8)}, + {"__rs_cosh_1", "__rs_cosh_16", FIXED(16)}, + + {"__fd_tanh_1", "__fd_tanh_2", FIXED(2)}, + {"__fd_tanh_1", "__fd_tanh_4", FIXED(4)}, + {"__fd_tanh_1", "__fd_tanh_8", FIXED(8)}, + + {"__fs_tanh_1", "__fs_tanh_4", FIXED(4)}, + {"__fs_tanh_1", "__fs_tanh_8", FIXED(8)}, + {"__fs_tanh_1", "__fs_tanh_16", FIXED(16)}, + + {"__pd_tanh_1", "__pd_tanh_2", FIXED(2)}, + {"__pd_tanh_1", "__pd_tanh_4", FIXED(4)}, + {"__pd_tanh_1", "__pd_tanh_8", FIXED(8)}, + + {"__ps_tanh_1", "__ps_tanh_4", FIXED(4)}, + {"__ps_tanh_1", "__ps_tanh_8", FIXED(8)}, + {"__ps_tanh_1", "__ps_tanh_16", FIXED(16)}, + + {"__rd_tanh_1", "__rd_tanh_2", FIXED(2)}, + {"__rd_tanh_1", "__rd_tanh_4", FIXED(4)}, + {"__rd_tanh_1", "__rd_tanh_8", FIXED(8)}, + + {"__rs_tanh_1", "__rs_tanh_4", FIXED(4)}, + {"__rs_tanh_1", "__rs_tanh_8", FIXED(8)}, + {"__rs_tanh_1", "__rs_tanh_16", FIXED(16)}, + + {"__fd_asin_1", "__fd_asin_2", FIXED(2)}, + {"__fd_asin_1", "__fd_asin_4", FIXED(4)}, + {"__fd_asin_1", "__fd_asin_8", FIXED(8)}, + + {"__fs_asin_1", "__fs_asin_4", FIXED(4)}, + {"__fs_asin_1", "__fs_asin_8", FIXED(8)}, + {"__fs_asin_1", "__fs_asin_16", FIXED(16)}, + + {"__pd_asin_1", "__pd_asin_2", FIXED(2)}, + {"__pd_asin_1", "__pd_asin_4", FIXED(4)}, + {"__pd_asin_1", "__pd_asin_8", FIXED(8)}, + + {"__ps_asin_1", "__ps_asin_4", FIXED(4)}, + {"__ps_asin_1", "__ps_asin_8", FIXED(8)}, + {"__ps_asin_1", "__ps_asin_16", FIXED(16)}, + + {"__rd_asin_1", "__rd_asin_2", FIXED(2)}, + {"__rd_asin_1", "__rd_asin_4", FIXED(4)}, + {"__rd_asin_1", "__rd_asin_8", FIXED(8)}, + + {"__rs_asin_1", "__rs_asin_4", FIXED(4)}, + {"__rs_asin_1", "__rs_asin_8", FIXED(8)}, + {"__rs_asin_1", "__rs_asin_16", FIXED(16)}, + + {"__fd_acos_1", "__fd_acos_2", FIXED(2)}, + {"__fd_acos_1", "__fd_acos_4", FIXED(4)}, + {"__fd_acos_1", "__fd_acos_8", FIXED(8)}, + + {"__fs_acos_1", "__fs_acos_4", FIXED(4)}, + {"__fs_acos_1", "__fs_acos_8", FIXED(8)}, + {"__fs_acos_1", "__fs_acos_16", FIXED(16)}, + + {"__pd_acos_1", "__pd_acos_2", FIXED(2)}, + {"__pd_acos_1", "__pd_acos_4", FIXED(4)}, + {"__pd_acos_1", "__pd_acos_8", FIXED(8)}, + + {"__ps_acos_1", "__ps_acos_4", FIXED(4)}, + {"__ps_acos_1", "__ps_acos_8", FIXED(8)}, + {"__ps_acos_1", "__ps_acos_16", FIXED(16)}, + + {"__rd_acos_1", "__rd_acos_2", FIXED(2)}, + {"__rd_acos_1", "__rd_acos_4", FIXED(4)}, + {"__rd_acos_1", "__rd_acos_8", FIXED(8)}, + + {"__rs_acos_1", "__rs_acos_4", FIXED(4)}, + {"__rs_acos_1", "__rs_acos_8", FIXED(8)}, + {"__rs_acos_1", "__rs_acos_16", FIXED(16)}, + + {"__fd_atan_1", "__fd_atan_2", FIXED(2)}, + {"__fd_atan_1", "__fd_atan_4", FIXED(4)}, + {"__fd_atan_1", "__fd_atan_8", FIXED(8)}, + + {"__fs_atan_1", "__fs_atan_4", FIXED(4)}, + {"__fs_atan_1", "__fs_atan_8", FIXED(8)}, + {"__fs_atan_1", "__fs_atan_16", FIXED(16)}, + + {"__pd_atan_1", "__pd_atan_2", FIXED(2)}, + {"__pd_atan_1", "__pd_atan_4", FIXED(4)}, + {"__pd_atan_1", "__pd_atan_8", FIXED(8)}, + + {"__ps_atan_1", "__ps_atan_4", FIXED(4)}, + {"__ps_atan_1", "__ps_atan_8", FIXED(8)}, + {"__ps_atan_1", "__ps_atan_16", FIXED(16)}, + + {"__rd_atan_1", "__rd_atan_2", FIXED(2)}, + {"__rd_atan_1", "__rd_atan_4", FIXED(4)}, + {"__rd_atan_1", "__rd_atan_8", FIXED(8)}, + + {"__rs_atan_1", "__rs_atan_4", FIXED(4)}, + {"__rs_atan_1", "__rs_atan_8", FIXED(8)}, + {"__rs_atan_1", "__rs_atan_16", FIXED(16)}, + + {"__fd_atan2_1", "__fd_atan2_2", FIXED(2)}, + {"__fd_atan2_1", "__fd_atan2_4", FIXED(4)}, + {"__fd_atan2_1", "__fd_atan2_8", FIXED(8)}, + + {"__fs_atan2_1", "__fs_atan2_4", FIXED(4)}, + {"__fs_atan2_1", "__fs_atan2_8", FIXED(8)}, + {"__fs_atan2_1", "__fs_atan2_16", FIXED(16)}, + + {"__pd_atan2_1", "__pd_atan2_2", FIXED(2)}, + {"__pd_atan2_1", "__pd_atan2_4", FIXED(4)}, + {"__pd_atan2_1", "__pd_atan2_8", FIXED(8)}, + + {"__ps_atan2_1", "__ps_atan2_4", FIXED(4)}, + {"__ps_atan2_1", "__ps_atan2_8", FIXED(8)}, + {"__ps_atan2_1", "__ps_atan2_16", FIXED(16)}, + + {"__rd_atan2_1", "__rd_atan2_2", FIXED(2)}, + {"__rd_atan2_1", "__rd_atan2_4", FIXED(4)}, + {"__rd_atan2_1", "__rd_atan2_8", FIXED(8)}, + + {"__rs_atan2_1", "__rs_atan2_4", FIXED(4)}, + {"__rs_atan2_1", "__rs_atan2_8", FIXED(8)}, + {"__rs_atan2_1", "__rs_atan2_16", FIXED(16)}, + + {"__fd_pow_1", "__fd_pow_2", FIXED(2)}, + {"__fd_pow_1", "__fd_pow_4", FIXED(4)}, + {"__fd_pow_1", "__fd_pow_8", FIXED(8)}, + + {"__fs_pow_1", "__fs_pow_4", FIXED(4)}, + {"__fs_pow_1", "__fs_pow_8", FIXED(8)}, + {"__fs_pow_1", "__fs_pow_16", FIXED(16)}, + + {"__pd_pow_1", "__pd_pow_2", FIXED(2)}, + {"__pd_pow_1", "__pd_pow_4", FIXED(4)}, + {"__pd_pow_1", "__pd_pow_8", FIXED(8)}, + + {"__ps_pow_1", "__ps_pow_4", FIXED(4)}, + {"__ps_pow_1", "__ps_pow_8", FIXED(8)}, + {"__ps_pow_1", "__ps_pow_16", FIXED(16)}, + + {"__rd_pow_1", "__rd_pow_2", FIXED(2)}, + {"__rd_pow_1", "__rd_pow_4", FIXED(4)}, + {"__rd_pow_1", "__rd_pow_8", FIXED(8)}, + + {"__rs_pow_1", "__rs_pow_4", FIXED(4)}, + {"__rs_pow_1", "__rs_pow_8", FIXED(8)}, + {"__rs_pow_1", "__rs_pow_16", FIXED(16)}, + + {"__fs_powi_1", "__fs_powi_4", FIXED(4)}, + {"__fs_powi_1", "__fs_powi_8", FIXED(8)}, + {"__fs_powi_1", "__fs_powi_16", FIXED(16)}, + + {"__ps_powi_1", "__ps_powi_4", FIXED(4)}, + {"__ps_powi_1", "__ps_powi_8", FIXED(8)}, + {"__ps_powi_1", "__ps_powi_16", FIXED(16)}, + + {"__rs_powi_1", "__rs_powi_4", FIXED(4)}, + {"__rs_powi_1", "__rs_powi_8", FIXED(8)}, + {"__rs_powi_1", "__rs_powi_16", FIXED(16)}, + + {"__fd_powi1_1", "__fd_powi1_2", FIXED(2)}, + {"__fd_powi1_1", "__fd_powi1_4", FIXED(4)}, + {"__fd_powi1_1", "__fd_powi1_8", FIXED(8)}, + + {"__fs_powi1_1", "__fs_powi1_4", FIXED(4)}, + {"__fs_powi1_1", "__fs_powi1_8", FIXED(8)}, + {"__fs_powi1_1", "__fs_powi1_16", FIXED(16)}, + + {"__pd_powi1_1", "__pd_powi1_2", FIXED(2)}, + {"__pd_powi1_1", "__pd_powi1_4", FIXED(4)}, + {"__pd_powi1_1", "__pd_powi1_8", FIXED(8)}, + + {"__ps_powi1_1", "__ps_powi1_4", FIXED(4)}, + {"__ps_powi1_1", "__ps_powi1_8", FIXED(8)}, + {"__ps_powi1_1", "__ps_powi1_16", FIXED(16)}, + + {"__rd_powi1_1", "__rd_powi1_2", FIXED(2)}, + {"__rd_powi1_1", "__rd_powi1_4", FIXED(4)}, + {"__rd_powi1_1", "__rd_powi1_8", FIXED(8)}, + + {"__rs_powi1_1", "__rs_powi1_4", FIXED(4)}, + {"__rs_powi1_1", "__rs_powi1_8", FIXED(8)}, + {"__rs_powi1_1", "__rs_powi1_16", FIXED(16)}, + + {"__fd_powk_1", "__fd_powk_2", FIXED(2)}, + {"__fd_powk_1", "__fd_powk_4", FIXED(4)}, + {"__fd_powk_1", "__fd_powk_8", FIXED(8)}, + + {"__fs_powk_1", "__fs_powk_4", FIXED(4)}, + {"__fs_powk_1", "__fs_powk_8", FIXED(8)}, + {"__fs_powk_1", "__fs_powk_16", FIXED(16)}, + + {"__pd_powk_1", "__pd_powk_2", FIXED(2)}, + {"__pd_powk_1", "__pd_powk_4", FIXED(4)}, + {"__pd_powk_1", "__pd_powk_8", FIXED(8)}, + + {"__ps_powk_1", "__ps_powk_4", FIXED(4)}, + {"__ps_powk_1", "__ps_powk_8", FIXED(8)}, + {"__ps_powk_1", "__ps_powk_16", FIXED(16)}, + + {"__rd_powk_1", "__rd_powk_2", FIXED(2)}, + {"__rd_powk_1", "__rd_powk_4", FIXED(4)}, + {"__rd_powk_1", "__rd_powk_8", FIXED(8)}, + + {"__rs_powk_1", "__rs_powk_4", FIXED(4)}, + {"__rs_powk_1", "__rs_powk_8", FIXED(8)}, + {"__rs_powk_1", "__rs_powk_16", FIXED(16)}, + + {"__fd_powk1_1", "__fd_powk1_2", FIXED(2)}, + {"__fd_powk1_1", "__fd_powk1_4", FIXED(4)}, + {"__fd_powk1_1", "__fd_powk1_8", FIXED(8)}, + + {"__fs_powk1_1", "__fs_powk1_4", FIXED(4)}, + {"__fs_powk1_1", "__fs_powk1_8", FIXED(8)}, + {"__fs_powk1_1", "__fs_powk1_16", FIXED(16)}, + + {"__pd_powk1_1", "__pd_powk1_2", FIXED(2)}, + {"__pd_powk1_1", "__pd_powk1_4", FIXED(4)}, + {"__pd_powk1_1", "__pd_powk1_8", FIXED(8)}, + + {"__ps_powk1_1", "__ps_powk1_4", FIXED(4)}, + {"__ps_powk1_1", "__ps_powk1_8", FIXED(8)}, + {"__ps_powk1_1", "__ps_powk1_16", FIXED(16)}, + + {"__rd_powk1_1", "__rd_powk1_2", FIXED(2)}, + {"__rd_powk1_1", "__rd_powk1_4", FIXED(4)}, + {"__rd_powk1_1", "__rd_powk1_8", FIXED(8)}, + + {"__rs_powk1_1", "__rs_powk1_4", FIXED(4)}, + {"__rs_powk1_1", "__rs_powk1_8", FIXED(8)}, + {"__rs_powk1_1", "__rs_powk1_16", FIXED(16)}, + + {"__fd_log10_1", "__fd_log10_2", FIXED(2)}, + {"__fd_log10_1", "__fd_log10_4", FIXED(4)}, + {"__fd_log10_1", "__fd_log10_8", FIXED(8)}, + + {"__fs_log10_1", "__fs_log10_4", FIXED(4)}, + {"__fs_log10_1", "__fs_log10_8", FIXED(8)}, + {"__fs_log10_1", "__fs_log10_16", FIXED(16)}, + + {"__pd_log10_1", "__pd_log10_2", FIXED(2)}, + {"__pd_log10_1", "__pd_log10_4", FIXED(4)}, + {"__pd_log10_1", "__pd_log10_8", FIXED(8)}, + + {"__ps_log10_1", "__ps_log10_4", FIXED(4)}, + {"__ps_log10_1", "__ps_log10_8", FIXED(8)}, + {"__ps_log10_1", "__ps_log10_16", FIXED(16)}, + + {"__rd_log10_1", "__rd_log10_2", FIXED(2)}, + {"__rd_log10_1", "__rd_log10_4", FIXED(4)}, + {"__rd_log10_1", "__rd_log10_8", FIXED(8)}, + + {"__rs_log10_1", "__rs_log10_4", FIXED(4)}, + {"__rs_log10_1", "__rs_log10_8", FIXED(8)}, + {"__rs_log10_1", "__rs_log10_16", FIXED(16)}, + + {"__fd_log_1", "__fd_log_2", FIXED(2)}, + {"__fd_log_1", "__fd_log_4", FIXED(4)}, + {"__fd_log_1", "__fd_log_8", FIXED(8)}, + + {"__fs_log_1", "__fs_log_4", FIXED(4)}, + {"__fs_log_1", "__fs_log_8", FIXED(8)}, + {"__fs_log_1", "__fs_log_16", FIXED(16)}, + + {"__pd_log_1", "__pd_log_2", FIXED(2)}, + {"__pd_log_1", "__pd_log_4", FIXED(4)}, + {"__pd_log_1", "__pd_log_8", FIXED(8)}, + + {"__ps_log_1", "__ps_log_4", FIXED(4)}, + {"__ps_log_1", "__ps_log_8", FIXED(8)}, + {"__ps_log_1", "__ps_log_16", FIXED(16)}, + + {"__rd_log_1", "__rd_log_2", FIXED(2)}, + {"__rd_log_1", "__rd_log_4", FIXED(4)}, + {"__rd_log_1", "__rd_log_8", FIXED(8)}, + + {"__rs_log_1", "__rs_log_4", FIXED(4)}, + {"__rs_log_1", "__rs_log_8", FIXED(8)}, + {"__rs_log_1", "__rs_log_16", FIXED(16)}, + + {"__fs_exp_1", "__fs_exp_4", FIXED(4)}, + {"__fs_exp_1", "__fs_exp_8", FIXED(8)}, + {"__fs_exp_1", "__fs_exp_16", FIXED(16)}, + + {"__pd_exp_1", "__pd_exp_2", FIXED(2)}, + {"__pd_exp_1", "__pd_exp_4", FIXED(4)}, + {"__pd_exp_1", "__pd_exp_8", FIXED(8)}, + + {"__ps_exp_1", "__ps_exp_4", FIXED(4)}, + {"__ps_exp_1", "__ps_exp_8", FIXED(8)}, + {"__ps_exp_1", "__ps_exp_16", FIXED(16)}, + + {"__rd_exp_1", "__rd_exp_2", FIXED(2)}, + {"__rd_exp_1", "__rd_exp_4", FIXED(4)}, + {"__rd_exp_1", "__rd_exp_8", FIXED(8)}, + + {"__rs_exp_1", "__rs_exp_4", FIXED(4)}, + {"__rs_exp_1", "__rs_exp_8", FIXED(8)}, + {"__rs_exp_1", "__rs_exp_16", FIXED(16)} + }; + addVectorizableFunctions(VecFuncs); + break; + } + case NoLibrary: break; } diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp index fd502eded0a0..95cd96f111bd 100644 --- a/llvm/lib/AsmParser/LLParser.cpp +++ b/llvm/lib/AsmParser/LLParser.cpp @@ -5068,6 +5068,22 @@ bool LLParser::parseDITemplateValueParameter(MDNode *&Result, bool IsDistinct) { /// isDefinition: true, templateParams: !3, /// declaration: !4, align: 8) bool LLParser::parseDIGlobalVariable(MDNode *&Result, bool IsDistinct) { +#ifdef ENABLE_CLASSIC_FLANG +#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ + OPTIONAL(name, MDStringField, (/* AllowEmpty */ true)); \ + OPTIONAL(scope, MDField, ); \ + OPTIONAL(linkageName, MDStringField, ); \ + OPTIONAL(file, MDField, ); \ + OPTIONAL(line, LineField, ); \ + OPTIONAL(type, MDField, ); \ + OPTIONAL(isLocal, MDBoolField, ); \ + OPTIONAL(isDefinition, MDBoolField, (true)); \ + OPTIONAL(templateParams, MDField, ); \ + OPTIONAL(declaration, MDField, ); \ + OPTIONAL(flags, DIFlagField, ); \ + OPTIONAL(align, MDUnsignedField, (0, UINT32_MAX)); \ + OPTIONAL(annotations, MDField, ); +#else #define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ OPTIONAL(name, MDStringField, (/* AllowEmpty */ false)); \ OPTIONAL(scope, MDField, ); \ @@ -5079,8 +5095,10 @@ bool LLParser::parseDIGlobalVariable(MDNode *&Result, bool IsDistinct) { OPTIONAL(isDefinition, MDBoolField, (true)); \ OPTIONAL(templateParams, MDField, ); \ OPTIONAL(declaration, MDField, ); \ + OPTIONAL(flags, DIFlagField, ); \ OPTIONAL(align, MDUnsignedField, (0, UINT32_MAX)); \ OPTIONAL(annotations, MDField, ); +#endif PARSE_MD_FIELDS(); #undef VISIT_MD_FIELDS @@ -5088,8 +5106,8 @@ bool LLParser::parseDIGlobalVariable(MDNode *&Result, bool IsDistinct) { GET_OR_DISTINCT(DIGlobalVariable, (Context, scope.Val, name.Val, linkageName.Val, file.Val, line.Val, type.Val, isLocal.Val, isDefinition.Val, - declaration.Val, templateParams.Val, align.Val, - annotations.Val)); + declaration.Val, templateParams.Val, flags.Val, + align.Val, annotations.Val)); return false; } diff --git a/llvm/lib/Bitcode/Reader/MetadataLoader.cpp b/llvm/lib/Bitcode/Reader/MetadataLoader.cpp index 13d53a35084d..c5729a3faf90 100644 --- a/llvm/lib/Bitcode/Reader/MetadataLoader.cpp +++ b/llvm/lib/Bitcode/Reader/MetadataLoader.cpp @@ -1883,25 +1883,43 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata( break; } case bitc::METADATA_GLOBAL_VAR: { - if (Record.size() < 11 || Record.size() > 13) + if (Record.size() < 11 || Record.size() > 14) return error("Invalid record"); IsDistinct = Record[0] & 1; unsigned Version = Record[0] >> 1; - if (Version == 2) { + if (Version == 3) { + // Add support for DIFlags + Metadata *Annotations = nullptr; + if (Record.size() > 13) + Annotations = getMDOrNull(Record[13]); + + MetadataList.assignValue( + GET_OR_DISTINCT( + DIGlobalVariable, + (Context, getMDOrNull(Record[1]), getMDString(Record[2]), + getMDString(Record[3]), getMDOrNull(Record[4]), Record[5], + getDITypeRefOrNull(Record[6]), Record[7], Record[8], + getMDOrNull(Record[9]), getMDOrNull(Record[10]), + static_cast(Record[11]), Record[12], + Annotations)), + NextMetadataNo); + + NextMetadataNo++; + } else if (Version == 2) { Metadata *Annotations = nullptr; if (Record.size() > 12) Annotations = getMDOrNull(Record[12]); MetadataList.assignValue( - GET_OR_DISTINCT(DIGlobalVariable, - (Context, getMDOrNull(Record[1]), - getMDString(Record[2]), getMDString(Record[3]), - getMDOrNull(Record[4]), Record[5], - getDITypeRefOrNull(Record[6]), Record[7], Record[8], - getMDOrNull(Record[9]), getMDOrNull(Record[10]), - Record[11], Annotations)), + GET_OR_DISTINCT( + DIGlobalVariable, + (Context, getMDOrNull(Record[1]), getMDString(Record[2]), + getMDString(Record[3]), getMDOrNull(Record[4]), Record[5], + getDITypeRefOrNull(Record[6]), Record[7], Record[8], + getMDOrNull(Record[9]), getMDOrNull(Record[10]), + DINode::FlagZero, Record[11], Annotations)), NextMetadataNo); NextMetadataNo++; @@ -1914,7 +1932,8 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata( (Context, getMDOrNull(Record[1]), getMDString(Record[2]), getMDString(Record[3]), getMDOrNull(Record[4]), Record[5], getDITypeRefOrNull(Record[6]), Record[7], Record[8], - getMDOrNull(Record[10]), nullptr, Record[11], nullptr)), + getMDOrNull(Record[10]), nullptr, DINode::FlagZero, Record[11], + nullptr)), NextMetadataNo); NextMetadataNo++; @@ -1947,7 +1966,8 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata( (Context, getMDOrNull(Record[1]), getMDString(Record[2]), getMDString(Record[3]), getMDOrNull(Record[4]), Record[5], getDITypeRefOrNull(Record[6]), Record[7], Record[8], - getMDOrNull(Record[10]), nullptr, AlignInBits, nullptr)); + getMDOrNull(Record[10]), nullptr, DINode::FlagZero, AlignInBits, + nullptr)); DIGlobalVariableExpression *DGVE = nullptr; if (Attach || Expr) diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp index d7e012fb6a9e..4a9c552ed7a2 100644 --- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -1980,7 +1980,7 @@ void ModuleBitcodeWriter::writeDITemplateValueParameter( void ModuleBitcodeWriter::writeDIGlobalVariable( const DIGlobalVariable *N, SmallVectorImpl &Record, unsigned Abbrev) { - const uint64_t Version = 2 << 1; + const uint64_t Version = 3 << 1; Record.push_back((uint64_t)N->isDistinct() | Version); Record.push_back(VE.getMetadataOrNullID(N->getScope())); Record.push_back(VE.getMetadataOrNullID(N->getRawName())); @@ -1992,6 +1992,7 @@ void ModuleBitcodeWriter::writeDIGlobalVariable( Record.push_back(N->isDefinition()); Record.push_back(VE.getMetadataOrNullID(N->getStaticDataMemberDeclaration())); Record.push_back(VE.getMetadataOrNullID(N->getTemplateParams())); + Record.push_back(N->getFlags()); Record.push_back(N->getAlignInBits()); Record.push_back(VE.getMetadataOrNullID(N->getAnnotations().get())); diff --git a/llvm/lib/CodeGen/AsmPrinter/DebugLocEntry.h b/llvm/lib/CodeGen/AsmPrinter/DebugLocEntry.h index d7ab2091967f..e2b99d523f27 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DebugLocEntry.h +++ b/llvm/lib/CodeGen/AsmPrinter/DebugLocEntry.h @@ -112,6 +112,29 @@ class DbgValueLoc { SmallVector ValueLocEntries; bool IsVariadic; + /// Type of entry that this represents. + enum EntryType { + E_Location, + E_Integer, + E_ConstantFP, + E_ConstantInt, + E_TargetIndexLocation + }; + enum EntryType EntryKind; + + /// Either a constant, + union { + int64_t Int; + const ConstantFP *CFP; + const ConstantInt *CIP; + } Constant; + + union { + /// Or a location in the machine frame. + MachineLocation Loc; + /// Or a location from target specific location. + TargetIndexLocation TIL; + }; public: DbgValueLoc(const DIExpression *Expr, ArrayRef Locs) @@ -146,6 +169,37 @@ public: assert(((Expr && Expr->isValid()) || !Loc.isLocation()) && "DBG_VALUE with a machine location must have a valid expression."); } + DbgValueLoc(const DIExpression *Expr, int64_t i) + : Expression(Expr), EntryKind(E_Integer) { + Constant.Int = i; + } + DbgValueLoc(const DIExpression *Expr, const ConstantFP *CFP) + : Expression(Expr), EntryKind(E_ConstantFP) { + Constant.CFP = CFP; + } + DbgValueLoc(const DIExpression *Expr, const ConstantInt *CIP) + : Expression(Expr), EntryKind(E_ConstantInt) { + Constant.CIP = CIP; + } + DbgValueLoc(const DIExpression *Expr, MachineLocation Loc) + : Expression(Expr), EntryKind(E_Location), Loc(Loc) { + assert(cast(Expr)->isValid()); + } + DbgValueLoc(const DIExpression *Expr, TargetIndexLocation Loc) + : Expression(Expr), EntryKind(E_TargetIndexLocation), TIL(Loc) {} + + bool isLocation() const { return EntryKind == E_Location; } + bool isTargetIndexLocation() const { + return EntryKind == E_TargetIndexLocation; + } + bool isInt() const { return EntryKind == E_Integer; } + bool isConstantFP() const { return EntryKind == E_ConstantFP; } + bool isConstantInt() const { return EntryKind == E_ConstantInt; } + int64_t getInt() const { return Constant.Int; } + const ConstantFP *getConstantFP() const { return Constant.CFP; } + const ConstantInt *getConstantInt() const { return Constant.CIP; } + MachineLocation getLoc() const { return Loc; } + TargetIndexLocation getTargetIndexLocation() const { return TIL; } bool isFragment() const { return getExpression()->isFragment(); } bool isEntryVal() const { return getExpression()->isEntryValue(); } @@ -160,6 +214,15 @@ public: LLVM_DUMP_METHOD void dump() const { for (const DbgValueLocEntry &DV : ValueLocEntries) DV.dump(); +// if (isLocation()) { +// llvm::dbgs() << "Loc = { reg=" << Loc.getReg() << " "; +// if (Loc.isIndirect()) +// llvm::dbgs() << "+0"; +// llvm::dbgs() << "} "; +// } else if (isConstantInt()) +// Constant.CIP->dump(); +// else if (isConstantFP()) +// Constant.CFP->dump(); if (Expression) Expression->dump(); } @@ -227,6 +290,9 @@ public: DebugLocStream::ListBuilder &List, const DIBasicType *BT, DwarfCompileUnit &TheCU); + +// void finalize(const AsmPrinter &AP, DebugLocStream::ListBuilder &List, +// const DIStringType *ST, DwarfCompileUnit &TheCU); }; /// Compare two DbgValueLocEntries for equality. @@ -255,6 +321,29 @@ inline bool operator==(const DbgValueLoc &A, const DbgValueLoc &B) { A.Expression == B.Expression && A.IsVariadic == B.IsVariadic; } +//inline bool operator==(const DbgValueLoc &A, +// const DbgValueLoc &B) { +// if (A.EntryKind != B.EntryKind) +// return false; +// +// if (A.Expression != B.Expression) +// return false; +// +// switch (A.EntryKind) { +// case DbgValueLoc::E_Location: +// return A.Loc == B.Loc; +// case DbgValueLoc::E_TargetIndexLocation: +// return A.TIL == B.TIL; +// case DbgValueLoc::E_Integer: +// return A.Constant.Int == B.Constant.Int; +// case DbgValueLoc::E_ConstantFP: +// return A.Constant.CFP == B.Constant.CFP; +// case DbgValueLoc::E_ConstantInt: +// return A.Constant.CIP == B.Constant.CIP; +// } +// llvm_unreachable("unhandled EntryKind"); +//} + /// Compare two fragments based on their offset. inline bool operator<(const DbgValueLoc &A, const DbgValueLoc &B) { diff --git a/llvm/lib/CodeGen/AsmPrinter/DebugLocStream.cpp b/llvm/lib/CodeGen/AsmPrinter/DebugLocStream.cpp index 8c6109880afc..2db86b2aa94a 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DebugLocStream.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DebugLocStream.cpp @@ -37,7 +37,10 @@ void DebugLocStream::finalizeEntry() { "Popped off more entries than are in the list"); } -DebugLocStream::ListBuilder::~ListBuilder() { +void DebugLocStream::ListBuilder::finalize() { + if (Finalized) + return; + Finalized = true; if (!Locs.finalizeList(Asm)) return; V.initializeDbgValue(&MI); diff --git a/llvm/lib/CodeGen/AsmPrinter/DebugLocStream.h b/llvm/lib/CodeGen/AsmPrinter/DebugLocStream.h index 10019a4720e6..9dfce4e4b093 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DebugLocStream.h +++ b/llvm/lib/CodeGen/AsmPrinter/DebugLocStream.h @@ -160,22 +160,25 @@ class DebugLocStream::ListBuilder { const MachineInstr &MI; size_t ListIndex; Optional TagOffset; + bool Finalized; public: ListBuilder(DebugLocStream &Locs, DwarfCompileUnit &CU, AsmPrinter &Asm, DbgVariable &V, const MachineInstr &MI) : Locs(Locs), Asm(Asm), V(V), MI(MI), ListIndex(Locs.startList(&CU)), - TagOffset(None) {} + TagOffset(None), Finalized(false) {} void setTagOffset(uint8_t TO) { TagOffset = TO; } + void finalize(); + /// Finalize the list. /// /// If the list is empty, delete it. Otherwise, finalize it by creating a /// temp symbol in \a Asm and setting up the \a DbgVariable. - ~ListBuilder(); + ~ListBuilder() { finalize(); } DebugLocStream &getLocs() { return Locs; } }; diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp index b26960cdebb8..32781c1da0ee 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp @@ -184,6 +184,9 @@ DIE *DwarfCompileUnit::getOrCreateGlobalVariableDIE( else addGlobalName(GV->getName(), *VariableDIE, DeclContext); + if (GV->isArtificial()) + addFlag(*VariableDIE, dwarf::DW_AT_artificial); + addAnnotation(*VariableDIE, GV->getAnnotations()); if (uint32_t AlignInBytes = GV->getAlignInBytes()) diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h index 61412cde34c8..2e41e1e06272 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h @@ -146,6 +146,14 @@ public: std::vector ExprRefedBaseTypes; +private: + DenseMap> *globalVarMap; +public: + void setGlobalVarMap( + DenseMap> *p = nullptr) { + globalVarMap = p; + } + /// Get or create global variable DIE. DIE * getOrCreateGlobalVariableDIE(const DIGlobalVariable *GV, diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp index 54af14429907..18087d607148 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -1215,11 +1215,17 @@ void DwarfDebug::beginModule(Module *M) { } DenseSet Processed; +#if 0 + CU.setGlobalVarMap(&GVMap); +#endif for (auto *GVE : CUNode->getGlobalVariables()) { DIGlobalVariable *GV = GVE->getVariable(); if (Processed.insert(GV).second) CU.getOrCreateGlobalVariableDIE(GV, sortGlobalExprs(GVMap[GV])); } +#if 0 + CU.setGlobalVarMap(); +#endif for (auto *Ty : CUNode->getEnumTypes()) CU.getOrCreateTypeDIE(cast(Ty)); @@ -1826,10 +1832,28 @@ DbgEntity *DwarfDebug::createConcreteEntity(DwarfCompileUnit &TheCU, return ConcreteEntities.back().get(); } +#if 0 +void DwarfDebug::populateDependentTypeMap() { + for (const auto &I : DbgValues) { + InlinedEntity IV = I.first; + if (I.second.empty()) + continue; + if (const DIVariable *DIV = dyn_cast(IV.first)) { + if (const DIStringType *ST = dyn_cast( + static_cast(DIV->getType()))) + if (const DIVariable *LV = ST->getStringLength()) + VariableInDependentType[LV] = ST; + } + } +} +#endif + // Find variables for each lexical scope. void DwarfDebug::collectEntityInfo(DwarfCompileUnit &TheCU, const DISubprogram *SP, DenseSet &Processed) { +// clearDependentTracking(); +// populateDependentTypeMap(); // Grab the variable info that was squirreled away in the MMI side-table. collectVariableInfoFromMFTable(TheCU, Processed); @@ -1848,6 +1872,11 @@ void DwarfDebug::collectEntityInfo(DwarfCompileUnit &TheCU, LexicalScope *Scope = nullptr; const DILocalVariable *LocalVar = cast(IV.first); +#if 0 + const DILocalVariable *LocalVar = dyn_cast(IV.first); + if (!LocalVar) + continue; +#endif if (const DILocation *IA = IV.second) Scope = LScopes.findInlinedScope(LocalVar->getScope(), IA); else @@ -1906,6 +1935,24 @@ void DwarfDebug::collectEntityInfo(DwarfCompileUnit &TheCU, // Finalize the entry by lowering it into a DWARF bytestream. for (auto &Entry : Entries) Entry.finalize(*Asm, List, BT, TheCU); +#if 0 + List.finalize(); + + if (VariableInDependentType.count(LocalVar)) { + const DIType *DT = VariableInDependentType[LocalVar]; + if (const DIStringType *ST = dyn_cast(DT)) { + unsigned Offset; + DbgVariable TVar = {LocalVar, IV.second}; + DebugLocStream::ListBuilder LB(DebugLocs, TheCU, *Asm, TVar, *MInsn); + for (auto &Entry : Entries) + Entry.finalize(*Asm, LB, ST, TheCU); + LB.finalize(); + Offset = TVar.getDebugLocListIndex(); + if (Offset != ~0u) + addStringTypeLoc(ST, Offset); + } + } +#endif } // For each InlinedEntity collected from DBG_LABEL instructions, convert to @@ -2677,6 +2724,35 @@ void DebugLocEntry::finalize(const AsmPrinter &AP, List.setTagOffset(*DwarfExpr.TagOffset); } +#if 0 +inline static DbgValueLoc mkDbgValueLoc(const DIExpression *expr, + DbgValueLoc &value) { + if (value.isInt()) + return DbgValueLoc(expr, value.getInt()); + if (value.isLocation()) + return DbgValueLoc(expr, value.getLoc()); + if (value.isConstantInt()) + return DbgValueLoc(expr, value.getConstantInt()); + assert(value.isConstantFP()); + return DbgValueLoc(expr, value.getConstantFP()); +} + +void DebugLocEntry::finalize(const AsmPrinter &AP, + DebugLocStream::ListBuilder &List, + const DIStringType *ST, + DwarfCompileUnit &TheCU) { + DebugLocStream::EntryBuilder Entry(List, Begin, End); + BufferByteStreamer Streamer = Entry.getStreamer(); + DebugLocDwarfExpression DwarfExpr(AP.getDwarfVersion(), Streamer, TheCU); + DbgValueLoc &Value = Values[0]; + assert(!Value.isFragment()); + assert(Values.size() == 1 && "only fragments may have >1 value"); + Value = mkDbgValueLoc(ST->getStringLengthExp(), Value); + DwarfDebug::emitDebugLocValue(AP, nullptr, Value, DwarfExpr); + DwarfExpr.finalize(); +} +#endif + void DwarfDebug::emitDebugLocEntryLocation(const DebugLocStream::Entry &Entry, const DwarfCompileUnit *CU) { // Emit the size. diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h index 31e4081b7141..b1bc16ee57a8 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h @@ -282,6 +282,8 @@ struct SymbolCU { DwarfCompileUnit *CU; }; +class DummyDwarfExpression; + /// The kind of accelerator tables we should emit. enum class AccelTableKind { Default, ///< Platform default. @@ -430,6 +432,8 @@ private: /// Map for tracking Fortran deferred CHARACTER lengths. DenseMap StringTypeLocMap; + DenseMap VariableInDependentType; + AddressPool AddrPool; /// Accelerator tables. @@ -624,6 +628,14 @@ private: /// Emit the reference to the section. void emitSectionReference(const DwarfCompileUnit &CU); +#if 0 + /// Populate dependent type variable map + void populateDependentTypeMap(); +#endif + + /// Clear dependent type tracking map + void clearDependentTracking() { VariableInDependentType.clear(); } + protected: /// Gather pre-function debug information. void beginFunctionImpl(const MachineFunction *MF) override; diff --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp index a29040b8c2aa..fa84587ac7ec 100644 --- a/llvm/lib/IR/AsmWriter.cpp +++ b/llvm/lib/IR/AsmWriter.cpp @@ -2254,6 +2254,7 @@ static void writeDIGlobalVariable(raw_ostream &Out, const DIGlobalVariable *N, Printer.printBool("isDefinition", N->isDefinition()); Printer.printMetadata("declaration", N->getRawStaticDataMemberDeclaration()); Printer.printMetadata("templateParams", N->getRawTemplateParams()); + Printer.printDIFlags("flags", N->getFlags()); Printer.printInt("align", N->getAlignInBits()); Printer.printMetadata("annotations", N->getRawAnnotations()); Out << ")"; diff --git a/llvm/lib/IR/DIBuilder.cpp b/llvm/lib/IR/DIBuilder.cpp index 34ffc9425281..41527399345c 100644 --- a/llvm/lib/IR/DIBuilder.cpp +++ b/llvm/lib/IR/DIBuilder.cpp @@ -737,14 +737,14 @@ DIGlobalVariableExpression *DIBuilder::createGlobalVariableExpression( DIScope *Context, StringRef Name, StringRef LinkageName, DIFile *F, unsigned LineNumber, DIType *Ty, bool IsLocalToUnit, bool isDefined, DIExpression *Expr, MDNode *Decl, MDTuple *TemplateParams, - uint32_t AlignInBits, DINodeArray Annotations) { + DINode::DIFlags Flags, uint32_t AlignInBits, DINodeArray Annotations) { checkGlobalVariableScope(Context); auto *GV = DIGlobalVariable::getDistinct( VMContext, cast_or_null(Context), Name, LinkageName, F, LineNumber, Ty, IsLocalToUnit, isDefined, - cast_or_null(Decl), TemplateParams, AlignInBits, - Annotations); + cast_or_null(Decl), TemplateParams, Flags, + AlignInBits, Annotations); if (!Expr) Expr = createExpression(); auto *N = DIGlobalVariableExpression::get(VMContext, GV, Expr); @@ -755,14 +755,14 @@ DIGlobalVariableExpression *DIBuilder::createGlobalVariableExpression( DIGlobalVariable *DIBuilder::createTempGlobalVariableFwdDecl( DIScope *Context, StringRef Name, StringRef LinkageName, DIFile *F, unsigned LineNumber, DIType *Ty, bool IsLocalToUnit, MDNode *Decl, - MDTuple *TemplateParams, uint32_t AlignInBits) { + MDTuple *TemplateParams, DINode::DIFlags Flags, uint32_t AlignInBits) { checkGlobalVariableScope(Context); return DIGlobalVariable::getTemporary( VMContext, cast_or_null(Context), Name, LinkageName, F, LineNumber, Ty, IsLocalToUnit, false, - cast_or_null(Decl), TemplateParams, AlignInBits, - nullptr) + cast_or_null(Decl), TemplateParams, Flags, + AlignInBits, nullptr) .release(); } diff --git a/llvm/lib/IR/DebugInfo.cpp b/llvm/lib/IR/DebugInfo.cpp index fd4b4170c0a7..68dcde9ffdc6 100644 --- a/llvm/lib/IR/DebugInfo.cpp +++ b/llvm/lib/IR/DebugInfo.cpp @@ -1450,12 +1450,13 @@ LLVMMetadataRef LLVMDIBuilderCreateGlobalVariableExpression( LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name, size_t NameLen, const char *Linkage, size_t LinkLen, LLVMMetadataRef File, unsigned LineNo, LLVMMetadataRef Ty, LLVMBool LocalToUnit, - LLVMMetadataRef Expr, LLVMMetadataRef Decl, uint32_t AlignInBits) { + LLVMMetadataRef Expr, LLVMMetadataRef Decl, LLVMDIFlags Flags, + uint32_t AlignInBits) { return wrap(unwrap(Builder)->createGlobalVariableExpression( unwrapDI(Scope), {Name, NameLen}, {Linkage, LinkLen}, unwrapDI(File), LineNo, unwrapDI(Ty), LocalToUnit, true, unwrap(Expr), unwrapDI(Decl), - nullptr, AlignInBits)); + nullptr, map_from_llvmDIFlags(Flags), AlignInBits)); } LLVMMetadataRef LLVMDIGlobalVariableExpressionGetVariable(LLVMMetadataRef GVE) { @@ -1500,11 +1501,12 @@ LLVMMetadataRef LLVMDIBuilderCreateTempGlobalVariableFwdDecl( LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name, size_t NameLen, const char *Linkage, size_t LnkLen, LLVMMetadataRef File, unsigned LineNo, LLVMMetadataRef Ty, LLVMBool LocalToUnit, - LLVMMetadataRef Decl, uint32_t AlignInBits) { + LLVMMetadataRef Decl, LLVMDIFlags Flags, uint32_t AlignInBits) { return wrap(unwrap(Builder)->createTempGlobalVariableFwdDecl( unwrapDI(Scope), {Name, NameLen}, {Linkage, LnkLen}, unwrapDI(File), LineNo, unwrapDI(Ty), LocalToUnit, - unwrapDI(Decl), nullptr, AlignInBits)); + unwrapDI(Decl), nullptr, map_from_llvmDIFlags(Flags), + AlignInBits)); } LLVMValueRef diff --git a/llvm/lib/IR/DebugInfoMetadata.cpp b/llvm/lib/IR/DebugInfoMetadata.cpp index 50799327c78a..185665303659 100644 --- a/llvm/lib/IR/DebugInfoMetadata.cpp +++ b/llvm/lib/IR/DebugInfoMetadata.cpp @@ -1129,15 +1129,16 @@ DIGlobalVariable::getImpl(LLVMContext &Context, Metadata *Scope, MDString *Name, MDString *LinkageName, Metadata *File, unsigned Line, Metadata *Type, bool IsLocalToUnit, bool IsDefinition, Metadata *StaticDataMemberDeclaration, - Metadata *TemplateParams, uint32_t AlignInBits, - Metadata *Annotations, StorageType Storage, - bool ShouldCreate) { + Metadata *TemplateParams, DIFlags Flags, + uint32_t AlignInBits, Metadata *Annotations, + StorageType Storage, bool ShouldCreate) { assert(isCanonical(Name) && "Expected canonical MDString"); assert(isCanonical(LinkageName) && "Expected canonical MDString"); DEFINE_GETIMPL_LOOKUP( DIGlobalVariable, (Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, IsDefinition, - StaticDataMemberDeclaration, TemplateParams, AlignInBits, Annotations)); + StaticDataMemberDeclaration, TemplateParams, Flags, AlignInBits, + Annotations)); Metadata *Ops[] = {Scope, Name, File, @@ -1148,7 +1149,8 @@ DIGlobalVariable::getImpl(LLVMContext &Context, Metadata *Scope, MDString *Name, TemplateParams, Annotations}; DEFINE_GETIMPL_STORE(DIGlobalVariable, - (Line, IsLocalToUnit, IsDefinition, AlignInBits), Ops); + (Line, IsLocalToUnit, IsDefinition, Flags, AlignInBits), + Ops); } DILocalVariable * diff --git a/llvm/lib/IR/LLVMContextImpl.h b/llvm/lib/IR/LLVMContextImpl.h index 47add940f603..f24761df9dfe 100644 --- a/llvm/lib/IR/LLVMContextImpl.h +++ b/llvm/lib/IR/LLVMContextImpl.h @@ -998,6 +998,7 @@ template <> struct MDNodeKeyImpl { bool IsDefinition; Metadata *StaticDataMemberDeclaration; Metadata *TemplateParams; + unsigned Flags; uint32_t AlignInBits; Metadata *Annotations; @@ -1005,20 +1006,21 @@ template <> struct MDNodeKeyImpl { Metadata *File, unsigned Line, Metadata *Type, bool IsLocalToUnit, bool IsDefinition, Metadata *StaticDataMemberDeclaration, Metadata *TemplateParams, + unsigned Flags, uint32_t AlignInBits, Metadata *Annotations) : Scope(Scope), Name(Name), LinkageName(LinkageName), File(File), Line(Line), Type(Type), IsLocalToUnit(IsLocalToUnit), IsDefinition(IsDefinition), StaticDataMemberDeclaration(StaticDataMemberDeclaration), - TemplateParams(TemplateParams), AlignInBits(AlignInBits), - Annotations(Annotations) {} + TemplateParams(TemplateParams), Flags(Flags), + AlignInBits(AlignInBits), Annotations(Annotations) {} MDNodeKeyImpl(const DIGlobalVariable *N) : Scope(N->getRawScope()), Name(N->getRawName()), LinkageName(N->getRawLinkageName()), File(N->getRawFile()), Line(N->getLine()), Type(N->getRawType()), IsLocalToUnit(N->isLocalToUnit()), IsDefinition(N->isDefinition()), StaticDataMemberDeclaration(N->getRawStaticDataMemberDeclaration()), - TemplateParams(N->getRawTemplateParams()), + TemplateParams(N->getRawTemplateParams()), Flags(N->getFlags()), AlignInBits(N->getAlignInBits()), Annotations(N->getRawAnnotations()) {} bool isKeyOf(const DIGlobalVariable *RHS) const { @@ -1030,6 +1032,7 @@ template <> struct MDNodeKeyImpl { StaticDataMemberDeclaration == RHS->getRawStaticDataMemberDeclaration() && TemplateParams == RHS->getRawTemplateParams() && + Flags == RHS->getFlags() && AlignInBits == RHS->getAlignInBits() && Annotations == RHS->getRawAnnotations(); } @@ -1044,7 +1047,7 @@ template <> struct MDNodeKeyImpl { // TODO: make hashing work fine with such situations return hash_combine(Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, IsDefinition, /* AlignInBits, */ - StaticDataMemberDeclaration, Annotations); + StaticDataMemberDeclaration, Flags, Annotations); } }; diff --git a/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp b/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp index 5b7aa304b987..2a45f5a87b6e 100644 --- a/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp +++ b/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp @@ -951,8 +951,8 @@ InstrProfiling::getOrCreateRegionCounters(InstrProfInstBase *Inc) { SP, CounterPtr->getName(), /*LinkageName=*/StringRef(), SP->getFile(), /*LineNo=*/0, DB.createUnspecifiedType("Profile Data Type"), CounterPtr->hasLocalLinkage(), /*IsDefined=*/true, /*Expr=*/nullptr, - /*Decl=*/nullptr, /*TemplateParams=*/nullptr, /*AlignInBits=*/0, - Annotations); + /*Decl=*/nullptr, /*TemplateParams=*/nullptr, + /*Flags=*/DINode::FlagZero, /*AlignInBits=*/0, Annotations); CounterPtr->addDebugInfo(DICounter); DB.finalize(); } else { diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp index 5fd4e45d80fb..28dce7f0857d 100644 --- a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp +++ b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp @@ -5574,8 +5574,10 @@ void LoopVectorizationCostModel::collectElementTypesForWidening() { if (ValuesToIgnore.count(&I)) continue; - // Only examine Loads, Stores and PHINodes. - if (!isa(I) && !isa(I) && !isa(I)) + // Examine Loads, Stores, PHINodes + // Also examine instructions which convert to a float/double + if (!isa(I) && !isa(I) && !isa(I) && + !isa(I) && !isa(I) && !isa(I)) continue; // Examine PHI nodes that are reduction variables. Update the type to diff --git a/llvm/test/Assembler/invalid-diglobalvariable-empty-name.ll b/llvm/test/Assembler/invalid-diglobalvariable-empty-name.ll index a4e69f3c8b75..d3c476a03198 100644 --- a/llvm/test/Assembler/invalid-diglobalvariable-empty-name.ll +++ b/llvm/test/Assembler/invalid-diglobalvariable-empty-name.ll @@ -1,4 +1,5 @@ ; RUN: not llvm-as < %s -disable-output 2>&1 | FileCheck %s +; UNSUPPORTED: classic_flang ; CHECK: :[[@LINE+1]]:30: error: 'name' cannot be empty !0 = !DIGlobalVariable(name: "") diff --git a/llvm/test/DebugInfo/Generic/fortran-subprogram-at.ll b/llvm/test/DebugInfo/Generic/fortran-subprogram-at.ll new file mode 100644 index 000000000000..988c388fe218 --- /dev/null +++ b/llvm/test/DebugInfo/Generic/fortran-subprogram-at.ll @@ -0,0 +1,24 @@ +; Test for DIFlagPure, DIFlagElement and DIFlagRecursive. These three +; DIFlags are used to attach DW_AT_pure, DW_AT_element, and DW_AT_recursive +; attributes to DW_TAG_subprogram DIEs. + +; RUN: llvm-as < %s | llvm-dis | llvm-as | llvm-dis | FileCheck %s +; CHECK: !DISubprogram({{.*}}, spFlags: DISPFlagDefinition | DISPFlagPure | DISPFlagElemental | DISPFlagRecursive, + +!llvm.module.flags = !{!0, !1} +!llvm.dbg.cu = !{!2} + +define void @subprgm() !dbg !6 { +L: + ret void +} + +!0 = !{i32 2, !"Dwarf Version", i32 2} +!1 = !{i32 1, !"Debug Info Version", i32 3} +!2 = distinct !DICompileUnit(language: DW_LANG_Fortran90, file: !3, producer: "Flang", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, retainedTypes: !4, globals: !4, imports: !4) +!3 = !DIFile(filename: "fortran-subprogram-at.f", directory: "/") +!4 = !{} +!5 = !DIBasicType(name: "real", size: 32, align: 32, encoding: DW_ATE_float) +!6 = distinct !DISubprogram(name: "subprgm", scope: !2, file: !3, line: 256, type: !7, scopeLine: 256, spFlags: DISPFlagDefinition | DISPFlagPure | DISPFlagElemental | DISPFlagRecursive, unit: !2) +!7 = !DISubroutineType(types: !8) +!8 = !{null, !5} diff --git a/llvm/test/DebugInfo/Generic/more-subprogram-attr.ll b/llvm/test/DebugInfo/Generic/more-subprogram-attr.ll new file mode 100644 index 000000000000..0533cf6b2367 --- /dev/null +++ b/llvm/test/DebugInfo/Generic/more-subprogram-attr.ll @@ -0,0 +1,38 @@ +; REQUIRES: object-emission + +; RUN: %llc_dwarf -O0 -filetype=obj < %s > %t +; RUN: llvm-dwarfdump -v -debug-info %t | FileCheck %s + +; Make sure we're emitting DW_AT_{pure,elemental,recursive}. +; CHECK: DW_TAG_subprogram +; CHECK-NOT: {{DW_TAG|NULL}} +; CHECK: DW_AT_name {{.*}} "main" +; CHECK-NOT: {{DW_TAG|NULL}} +; CHECK: DW_AT_pure [DW_FORM_flag_present] (true) +; CHECK: DW_AT_elemental [DW_FORM_flag_present] (true) +; CHECK: DW_AT_recursive [DW_FORM_flag_present] (true) + +define dso_local i32 @main() !dbg !7 { +entry: + %retval = alloca i32, align 4 + store i32 0, i32* %retval, align 4 + ret i32 0, !dbg !12 +} + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!3, !4, !5} +!llvm.ident = !{!6} + +!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, nameTableKind: None) +!1 = !DIFile(filename: "x.c", directory: "/tmp") +!2 = !{} +!3 = !{i32 2, !"Dwarf Version", i32 4} +!4 = !{i32 2, !"Debug Info Version", i32 3} +!5 = !{i32 1, !"wchar_size", i32 4} +!6 = !{!"clang"} +!7 = distinct !DISubprogram(name: "main", scope: !8, file: !8, line: 1, type: !9, scopeLine: 2, spFlags: DISPFlagDefinition | DISPFlagPure | DISPFlagElemental | DISPFlagRecursive, unit: !0, retainedNodes: !2) +!8 = !DIFile(filename: "x.c", directory: "/tmp") +!9 = !DISubroutineType(types: !10) +!10 = !{!11} +!11 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!12 = !DILocation(line: 3, column: 3, scope: !7) diff --git a/llvm/test/DebugInfo/X86/DICommonBlock.ll b/llvm/test/DebugInfo/X86/DICommonBlock.ll new file mode 100644 index 000000000000..6cfb7a90640d --- /dev/null +++ b/llvm/test/DebugInfo/X86/DICommonBlock.ll @@ -0,0 +1,36 @@ +; ModuleID = 'none.f90' +; RUN: llc %s -o %t -filetype=obj +; RUN: llvm-dwarfdump -debug-info %t | FileCheck %s +; CHECK: DW_TAG_common_block + +target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-apple-macosx" + +@common_a = common global [32 x i8] zeroinitializer, align 8, !dbg !13 + +define i32 @subr() !dbg !9 { + %1 = getelementptr inbounds [32 x i8], [32 x i8]* @common_a, i64 0, i32 8 + %2 = bitcast i8* %1 to i32* + %3 = load i32, i32* %2 + ret i32 %3 +} + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!6, !7} +!llvm.ident = !{!8} + +!0 = distinct !DICompileUnit(language: DW_LANG_Fortran90, file: !1, producer: "PGI Fortran", isOptimized: false, runtimeVersion: 2, emissionKind: FullDebug, retainedTypes: !14, globals: !2) +!1 = !DIFile(filename: "none.f90", directory: "/not/here/") +!2 = !{!13} +!3 = !{} +!4 = !DIGlobalVariable(name: "common /a/", scope: !5, file: !1, line: 4, isLocal: false, isDefinition: true, type: !12) +!5 = !DICommonBlock(scope: !9, declaration: !4, name: "a", file: !1, line: 4) +!6 = !{i32 2, !"Dwarf Version", i32 4} +!7 = !{i32 2, !"Debug Info Version", i32 3} +!8 = !{!"PGI Fortran"} +!9 = distinct !DISubprogram(name: "subrtn", scope: !0, file: !1, line: 1, type: !10, isLocal: false, isDefinition: true, unit: !0) +!10 = !DISubroutineType(types: !11) +!11 = !{!12, !12} +!12 = !DIBasicType(name: "int", size: 32) +!13 = !DIGlobalVariableExpression(var: !4, expr: !DIExpression()) +!14 = !{!12, !10} diff --git a/llvm/test/lit.cfg.py b/llvm/test/lit.cfg.py index 75a38b4c5dad..f019626be854 100644 --- a/llvm/test/lit.cfg.py +++ b/llvm/test/lit.cfg.py @@ -487,3 +487,6 @@ if 'aix' in config.target_triple: # "OBJECT_MODE" to 'any' by default on AIX OS. if 'system-aix' in config.available_features: config.environment['OBJECT_MODE'] = 'any' + +if config.use_classic_flang: + config.available_features.add("classic_flang") diff --git a/llvm/test/lit.site.cfg.py.in b/llvm/test/lit.site.cfg.py.in index 09210e2e56d4..ca456defe14a 100644 --- a/llvm/test/lit.site.cfg.py.in +++ b/llvm/test/lit.site.cfg.py.in @@ -62,6 +62,7 @@ config.llvm_raevict_model_autogenerated = @LLVM_RAEVICT_MODEL_AUTOGENERATED@ config.expensive_checks = @LLVM_ENABLE_EXPENSIVE_CHECKS@ config.dxil_tests = @LLVM_INCLUDE_DXIL_TESTS@ config.have_llvm_driver = @LLVM_TOOL_LLVM_DRIVER_BUILD@ +config.use_classic_flang = @LLVM_ENABLE_CLASSIC_FLANG@ import lit.llvm lit.llvm.initialize(lit_config, config) diff --git a/llvm/tools/llvm-c-test/debuginfo.c b/llvm/tools/llvm-c-test/debuginfo.c index d33e40f5f4f3..984c5da49406 100644 --- a/llvm/tools/llvm-c-test/debuginfo.c +++ b/llvm/tools/llvm-c-test/debuginfo.c @@ -63,7 +63,7 @@ int llvm_test_dibuilder(void) { LLVMDIBuilderCreateConstantValueExpression(DIB, 0); LLVMDIBuilderCreateGlobalVariableExpression( DIB, Module, "globalClass", 11, "", 0, File, 1, ClassTy, true, - GlobalClassValueExpr, NULL, 0); + GlobalClassValueExpr, NULL, LLVMDIFlagZero, 0); LLVMMetadataRef Int64Ty = LLVMDIBuilderCreateBasicType(DIB, "Int64", 5, 64, 0, LLVMDIFlagZero); @@ -74,7 +74,7 @@ int llvm_test_dibuilder(void) { LLVMDIBuilderCreateConstantValueExpression(DIB, 0); LLVMDIBuilderCreateGlobalVariableExpression( DIB, Module, "global", 6, "", 0, File, 1, Int64TypeDef, true, - GlobalVarValueExpr, NULL, 0); + GlobalVarValueExpr, NULL, LLVMDIFlagZero, 0); LLVMMetadataRef NameSpace = LLVMDIBuilderCreateNameSpace(DIB, Module, "NameSpace", 9, false); diff --git a/llvm/unittests/IR/MetadataTest.cpp b/llvm/unittests/IR/MetadataTest.cpp index 9dd49d04405f..baa33bae1d6d 100644 --- a/llvm/unittests/IR/MetadataTest.cpp +++ b/llvm/unittests/IR/MetadataTest.cpp @@ -2665,12 +2665,13 @@ TEST_F(DIGlobalVariableTest, get) { DIDerivedType *StaticDataMemberDeclaration = cast(getDerivedType()); + DINode::DIFlags Flags = static_cast(7); uint32_t AlignInBits = 8; auto *N = DIGlobalVariable::get( Context, Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, - IsDefinition, StaticDataMemberDeclaration, templateParams, AlignInBits, - nullptr); + IsDefinition, StaticDataMemberDeclaration, templateParams, Flags, + AlignInBits, nullptr); EXPECT_EQ(dwarf::DW_TAG_variable, N->getTag()); EXPECT_EQ(Scope, N->getScope()); @@ -2683,57 +2684,66 @@ TEST_F(DIGlobalVariableTest, get) { EXPECT_EQ(IsDefinition, N->isDefinition()); EXPECT_EQ(StaticDataMemberDeclaration, N->getStaticDataMemberDeclaration()); EXPECT_EQ(templateParams, N->getTemplateParams()); + EXPECT_EQ(Flags, N->getFlags()); EXPECT_EQ(AlignInBits, N->getAlignInBits()); EXPECT_EQ(N, DIGlobalVariable::get(Context, Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, IsDefinition, StaticDataMemberDeclaration, - templateParams, AlignInBits, nullptr)); + templateParams, Flags, AlignInBits, + nullptr)); EXPECT_NE(N, DIGlobalVariable::get( Context, getSubprogram(), Name, LinkageName, File, Line, Type, IsLocalToUnit, IsDefinition, - StaticDataMemberDeclaration, templateParams, AlignInBits, - nullptr)); + StaticDataMemberDeclaration, templateParams, Flags, + AlignInBits, nullptr)); EXPECT_NE(N, DIGlobalVariable::get(Context, Scope, "other", LinkageName, File, Line, Type, IsLocalToUnit, IsDefinition, StaticDataMemberDeclaration, - templateParams, AlignInBits, nullptr)); + templateParams, Flags, AlignInBits, + nullptr)); EXPECT_NE(N, DIGlobalVariable::get(Context, Scope, Name, "other", File, Line, Type, IsLocalToUnit, IsDefinition, StaticDataMemberDeclaration, - templateParams, AlignInBits, nullptr)); + templateParams, Flags, AlignInBits, nullptr)); EXPECT_NE(N, DIGlobalVariable::get(Context, Scope, Name, LinkageName, getFile(), Line, Type, IsLocalToUnit, IsDefinition, StaticDataMemberDeclaration, - templateParams, AlignInBits, nullptr)); + templateParams, Flags, AlignInBits, nullptr)); EXPECT_NE(N, DIGlobalVariable::get(Context, Scope, Name, LinkageName, File, Line + 1, Type, IsLocalToUnit, IsDefinition, StaticDataMemberDeclaration, - templateParams, AlignInBits, nullptr)); + templateParams, Flags, AlignInBits, nullptr)); EXPECT_NE(N, DIGlobalVariable::get(Context, Scope, Name, LinkageName, File, Line, getDerivedType(), IsLocalToUnit, IsDefinition, StaticDataMemberDeclaration, - templateParams, AlignInBits, nullptr)); + templateParams, Flags, AlignInBits, nullptr)); EXPECT_NE(N, DIGlobalVariable::get(Context, Scope, Name, LinkageName, File, Line, Type, !IsLocalToUnit, IsDefinition, StaticDataMemberDeclaration, - templateParams, AlignInBits, nullptr)); + templateParams, Flags, AlignInBits, nullptr)); EXPECT_NE(N, DIGlobalVariable::get(Context, Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, !IsDefinition, StaticDataMemberDeclaration, - templateParams, AlignInBits, nullptr)); + templateParams, Flags, AlignInBits, nullptr)); EXPECT_NE(N, DIGlobalVariable::get(Context, Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, IsDefinition, cast(getDerivedType()), - templateParams, AlignInBits, nullptr)); + templateParams, Flags, AlignInBits, nullptr)); EXPECT_NE(N, DIGlobalVariable::get(Context, Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, IsDefinition, StaticDataMemberDeclaration, nullptr, + Flags, AlignInBits, nullptr)); + EXPECT_NE(N, DIGlobalVariable::get(Context, Scope, Name, LinkageName, File, + Line, Type, IsLocalToUnit, IsDefinition, + StaticDataMemberDeclaration, + templateParams, + static_cast(Flags + 1), AlignInBits, nullptr)); EXPECT_NE(N, DIGlobalVariable::get(Context, Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, IsDefinition, StaticDataMemberDeclaration, - templateParams, (AlignInBits << 1), + templateParams, Flags, (AlignInBits << 1), nullptr)); TempDIGlobalVariable Temp = N->clone(); @@ -2756,16 +2766,17 @@ TEST_F(DIGlobalVariableExpressionTest, get) { auto *Expr2 = DIExpression::get(Context, {1, 2, 3}); DIDerivedType *StaticDataMemberDeclaration = cast(getDerivedType()); + DINode::DIFlags Flags = static_cast(7); uint32_t AlignInBits = 8; auto *Var = DIGlobalVariable::get( Context, Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, - IsDefinition, StaticDataMemberDeclaration, templateParams, AlignInBits, - nullptr); + IsDefinition, StaticDataMemberDeclaration, templateParams, Flags, + AlignInBits, nullptr); auto *Var2 = DIGlobalVariable::get( Context, Scope, "other", LinkageName, File, Line, Type, IsLocalToUnit, - IsDefinition, StaticDataMemberDeclaration, templateParams, AlignInBits, - nullptr); + IsDefinition, StaticDataMemberDeclaration, templateParams, Flags, + AlignInBits, nullptr); auto *N = DIGlobalVariableExpression::get(Context, Var, Expr); EXPECT_EQ(Var, N->getVariable()); -- Gitee From e25ce8a05052a1039cdb45ffd87af6db49b3e95c Mon Sep 17 00:00:00 2001 From: Bryan Chan Date: Sun, 1 May 2022 21:43:45 -0400 Subject: [PATCH 04/33] [ClassicFlang][Driver] Coexist with LLVM Flang Make TableGen respect the ENABLE_CLASSIC_FLANG macro and better separate the driver options that are mutually exclusive. When the macro is defined, do not build LLVM Flang at all. --- clang/include/clang/Driver/CMakeLists.txt | 6 +- clang/include/clang/Driver/Options.td | 64 +++++++++++--------- clang/include/clang/Driver/ToolChain.h | 4 ++ clang/lib/Driver/CMakeLists.txt | 7 ++- clang/lib/Driver/ToolChain.cpp | 6 ++ clang/lib/Driver/ToolChains/Clang.cpp | 8 +-- clang/lib/Driver/ToolChains/ClassicFlang.cpp | 16 ++--- clang/lib/Driver/ToolChains/CommonArgs.cpp | 10 ++- clang/lib/Driver/ToolChains/CommonArgs.h | 2 + clang/lib/Driver/ToolChains/Cuda.cpp | 2 + clang/lib/Driver/ToolChains/Cuda.h | 8 ++- clang/lib/Driver/ToolChains/Gnu.cpp | 2 + clang/lib/Driver/ToolChains/Linux.cpp | 2 + clang/lib/Driver/ToolChains/Linux.h | 2 + 14 files changed, 90 insertions(+), 49 deletions(-) diff --git a/clang/include/clang/Driver/CMakeLists.txt b/clang/include/clang/Driver/CMakeLists.txt index a9d988047920..8543ae37ca4c 100644 --- a/clang/include/clang/Driver/CMakeLists.txt +++ b/clang/include/clang/Driver/CMakeLists.txt @@ -1,3 +1,7 @@ set(LLVM_TARGET_DEFINITIONS Options.td) -tablegen(LLVM Options.inc -gen-opt-parser-defs) +if(LLVM_ENABLE_CLASSIC_FLANG) + tablegen(LLVM Options.inc -DENABLE_CLASSIC_FLANG -gen-opt-parser-defs) +else() + tablegen(LLVM Options.inc -gen-opt-parser-defs) +endif() add_public_tablegen_target(ClangDriverOptions) diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 29b328429752..09508e82f4bb 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -533,7 +533,7 @@ class InternalDriverOpt : Group, Flags<[NoXarchOption, HelpHidden]>; def driver_mode : Joined<["--"], "driver-mode=">, Group, Flags<[CoreOption, NoXarchOption, HelpHidden]>, - HelpText<"Set the driver mode to either 'gcc', 'g++', 'cpp', 'cl', or 'fortran'">; + HelpText<"Set the driver mode to one of: 'gcc', 'g++', 'cpp', 'cl', or 'flang'">; def rsp_quoting : Joined<["--"], "rsp-quoting=">, Group, Flags<[CoreOption, NoXarchOption, HelpHidden]>, HelpText<"Set the rsp quoting to either 'posix', or 'windows'">; @@ -4790,12 +4790,6 @@ defm devirtualize : BooleanFFlag<"devirtualize">, Group, Group; -// gfortran options that we recognize in the driver and pass along when -// invoking GCC to compile Fortran code. -def flang_rt_Group : OptionGroup<"Flang runtime library Group">; -def pgi_fortran_Group : OptionGroup<"PGI Fortran compatibility Group">, - Flags<[HelpHidden]>; - // Generic gfortran options. def A_DASH : Joined<["-"], "A-">, Group; def static_libgfortran : Flag<["-"], "static-libgfortran">, Group; @@ -4817,8 +4811,6 @@ def fmax_stack_var_size_EQ : Joined<["-"], "fmax-stack-var-size=">, Group, Group; // "f" flags for gfortran. defm aggressive_function_elimination : BooleanFFlag<"aggressive-function-elimination">, Group; defm align_commons : BooleanFFlag<"align-commons">, Group; @@ -4830,19 +4822,13 @@ defm check_array_temporaries : BooleanFFlag<"check-array-temporaries">, Group, Group; defm d_lines_as_code : BooleanFFlag<"d-lines-as-code">, Group; defm d_lines_as_comments : BooleanFFlag<"d-lines-as-comments">, Group; -def default_integer_8_fno : Flag<["-"], "fno-default-integer-8">, Group; -def default_real_8_fno : Flag<["-"], "fno-default-real-8">, Group; defm dollar_ok : BooleanFFlag<"dollar-ok">, Group; defm dump_fortran_optimized : BooleanFFlag<"dump-fortran-optimized">, Group; defm dump_fortran_original : BooleanFFlag<"dump-fortran-original">, Group; defm dump_parse_tree : BooleanFFlag<"dump-parse-tree">, Group; defm external_blas : BooleanFFlag<"external-blas">, Group; defm f2c : BooleanFFlag<"f2c">, Group; -def fixed_form_off : Flag<["-"], "fno-fixed-form">, Group, - HelpText<"Disable fixed-form format for Fortran">; -def free_form_off : Flag<["-"], "fno-free-form">, Group, - HelpText<"Disable free-form format for Fortran">; -defm frontend_optimize : BooleanFFlag<"frontend-optimize">, Group; +defm frontend_optimize : BooleanFFlag<"frontend-optimize">, Group; defm init_local_zero : BooleanFFlag<"init-local-zero">, Group; defm integer_4_integer_8 : BooleanFFlag<"integer-4-integer-8">, Group; defm max_identifier_length : BooleanFFlag<"max-identifier-length">, Group; @@ -4894,9 +4880,9 @@ def Xflang : Separate<["-"], "Xflang">, let Flags = [FC1Option, FlangOption, FlangOnlyOption] in { -def cpp : Flag<["-"], "cpp">, Group, +def cpp : Flag<["-"], "cpp">, Group, HelpText<"Enable predefined and command line preprocessor macros">; -def nocpp : Flag<["-"], "nocpp">, Group, +def nocpp : Flag<["-"], "nocpp">, Group, HelpText<"Disable predefined and command line preprocessor macros">; def module_dir : JoinedOrSeparate<["-"], "module-dir">, MetaVarName<"">, HelpText<"Put MODULE files in ">, @@ -4904,34 +4890,48 @@ def module_dir : JoinedOrSeparate<["-"], "module-dir">, MetaVarName<"">, It is also added to the list of directories to be searched by an USE statement. The default is the current directory.}]>; +#ifdef ENABLE_CLASSIC_FLANG +// Define a group for Fortran source format options. +def fortran_format_Group : OptionGroup<"Fortran format Group">, Group; def ffixed_form : Flag<["-"], "ffixed-form">, Group, HelpText<"Process source files in fixed form">; -#ifdef ENABLE_CLASSIC_FLANG def fno_fixed_form : Flag<["-"], "fno-fixed-form">, Group, HelpText<"Disable fixed-form format for Fortran">; -#endif def ffree_form : Flag<["-"], "ffree-form">, Group, HelpText<"Process source files in free form">; -#ifdef ENABLE_CLASSIC_FLANG def fno_free_form : Flag<["-"], "fno-free-form">, Group, HelpText<"Disable free-form format for Fortran">; -#endif -def ffixed_line_length_EQ : Joined<["-"], "ffixed-line-length=">, Group, +def ffixed_line_length_VALUE : Joined<["-"], "ffixed-line-length-">, Group, + HelpText<"Set line length in fixed-form format Fortran, current supporting only 72 and 132 characters">; +#else +def ffixed_form : Flag<["-"], "ffixed-form">, Group, + HelpText<"Process source files in fixed form">; +def ffree_form : Flag<["-"], "ffree-form">, Group, + HelpText<"Process source files in free form">; +def ffixed_line_length_EQ : Joined<["-"], "ffixed-line-length=">, Group, HelpText<"Use as character line width in fixed mode">, DocBrief<[{Set column after which characters are ignored in typical fixed-form lines in the source file}]>; -def ffixed_line_length_VALUE : Joined<["-"], "ffixed-line-length-">, Group, - HelpText<"Set line length in fixed-form format Fortran, current supporting only 72 and 132 characters">; +def ffixed_line_length_VALUE : Joined<["-"], "ffixed-line-length-">, Group, Alias; +#endif + def fopenacc : Flag<["-"], "fopenacc">, Group, HelpText<"Enable OpenACC">; -def fdefault_double_8 : Flag<["-"],"fdefault-double-8">, Group, +def fdefault_double_8 : Flag<["-"],"fdefault-double-8">, Group, HelpText<"Set the default double precision kind to an 8 byte wide type">; -def fdefault_integer_8 : Flag<["-"],"fdefault-integer-8">, Group, +def fdefault_integer_8 : Flag<["-"],"fdefault-integer-8">, Group, HelpText<"Set the default integer kind to an 8 byte wide type">; -def fdefault_real_8 : Flag<["-"],"fdefault-real-8">, Group, +#ifdef ENABLE_CLASSIC_FLANG +def fno_default_integer_8 : Flag<["-"], "fno-default-integer-8">, Group; +#endif +def fdefault_real_8 : Flag<["-"],"fdefault-real-8">, Group, HelpText<"Set the default real kind to an 8 byte wide type">; +#ifdef ENABLE_CLASSIC_FLANG +def fno_default_real_8 : Flag<["-"], "fno-default-real-8">, Group; +#endif def flarge_sizes : Flag<["-"],"flarge-sizes">, Group, HelpText<"Use INTEGER(KIND=8) for the result type in size-related intrinsics">; + def falternative_parameter_statement : Flag<["-"], "falternative-parameter-statement">, Group, HelpText<"Enable the old style PARAMETER statement">; def fintrinsic_modules_path : Separate<["-"], "fintrinsic-modules-path">, Group, MetaVarName<"">, @@ -6948,6 +6948,13 @@ def enable_16bit_types : DXCFlag<"enable-16bit-types">, Alias HelpText<"Enable 16-bit types and disable min precision types." "Available in HLSL 2018 and shader model 6.2.">; +#ifdef ENABLE_CLASSIC_FLANG +// Classic Flang options that we recognize in the driver and pass along when +// invoking flang1/flang2 to compile Fortran code. +def flang_rt_Group : OptionGroup<"Flang runtime library Group">; +def pgi_fortran_Group : OptionGroup<"PGI Fortran compatibility Group">, + Flags<[HelpHidden]>; + // Classic Flang-specific options multiclass BooleanKFlag { def _on : Flag<["-"], "K"#name>; @@ -7080,3 +7087,4 @@ def Hq_EQ : Joined<["-"], "Hq,">, Group; def Mqq_EQ : Joined<["-"], "Mqq,">, Group; def Hqq_EQ : Joined<["-"], "Hqq,">, Group; def Wh_EQ : Joined<["-"], "Wh,">, Group; +#endif diff --git a/clang/include/clang/Driver/ToolChain.h b/clang/include/clang/Driver/ToolChain.h index 66cd1823033d..842e93b3a09c 100644 --- a/clang/include/clang/Driver/ToolChain.h +++ b/clang/include/clang/Driver/ToolChain.h @@ -623,6 +623,7 @@ public: AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args) const; +#ifdef ENABLE_CLASSIC_FLANG /// \brief Add the flang arguments for system include paths. /// /// This routine is responsible for adding the -stdinc argument to @@ -630,6 +631,7 @@ public: virtual void AddFlangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &Flang1Args) const { } +#endif /// Add options that need to be passed to cc1 for this target. virtual void addClangTargetOptions(const llvm::opt::ArgList &DriverArgs, @@ -728,10 +730,12 @@ public: virtual void AddHIPRuntimeLibArgs(const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs) const {} +#ifdef ENABLE_CLASSIC_FLANG /// AddFortranStdlibLibArgs - Add the system specific linker arguments to use /// for the given Fortran runtime library type. virtual void AddFortranStdlibLibArgs(const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs) const; +#endif /// Return sanitizers which are available in this toolchain. virtual SanitizerMask getSupportedSanitizers() const; diff --git a/clang/lib/Driver/CMakeLists.txt b/clang/lib/Driver/CMakeLists.txt index 24a795ba09ad..786bb895d5bb 100644 --- a/clang/lib/Driver/CMakeLists.txt +++ b/clang/lib/Driver/CMakeLists.txt @@ -13,7 +13,9 @@ if(WIN32) endif() if(LLVM_ENABLE_CLASSIC_FLANG) - set(CLASSIC_FLANG_FILES ToolChains/ClassicFlang.cpp) + set(TOOLCHAINS_FLANG_CPP ToolChains/ClassicFlang.cpp) +else() + set(TOOLCHAINS_FLANG_CPP ToolChains/Flang.cpp) endif() add_clang_library(clangDriver @@ -55,7 +57,7 @@ add_clang_library(clangDriver ToolChains/Cuda.cpp ToolChains/Darwin.cpp ToolChains/DragonFly.cpp - ToolChains/Flang.cpp + ${TOOLCHAINS_FLANG_CPP} ToolChains/FreeBSD.cpp ToolChains/Fuchsia.cpp ToolChains/Gnu.cpp @@ -90,7 +92,6 @@ add_clang_library(clangDriver ToolChains/ZOS.cpp Types.cpp XRayArgs.cpp - ${CLASSIC_FLANG_FILES} DEPENDS ClangDriverOptions diff --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp index 8626c338dda3..87f4e670daa2 100644 --- a/clang/lib/Driver/ToolChain.cpp +++ b/clang/lib/Driver/ToolChain.cpp @@ -299,9 +299,13 @@ Tool *ToolChain::getClang() const { } Tool *ToolChain::getFlang() const { +#ifndef ENABLE_CLASSIC_FLANG if (!Flang) Flang.reset(new tools::Flang(*this)); return Flang.get(); +#else + llvm_unreachable("Flang is not supported by this toolchain"); +#endif } Tool *ToolChain::buildAssembler() const { @@ -1049,6 +1053,7 @@ void ToolChain::AddCCKextLibArgs(const ArgList &Args, CmdArgs.push_back("-lcc_kext"); } +#ifdef ENABLE_CLASSIC_FLANG void ToolChain::AddFortranStdlibLibArgs(const ArgList &Args, ArgStringList &CmdArgs) const { bool staticFlangLibs = false; @@ -1087,6 +1092,7 @@ void ToolChain::AddFortranStdlibLibArgs(const ArgList &Args, // Allways link Fortran executables with Pthreads CmdArgs.push_back("-lpthread"); } +#endif bool ToolChain::isFastMathRuntimeAvailable(const ArgList &Args, std::string &Path) const { diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 1f7b81a6f04b..a8fd2ae6bfcb 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -5096,14 +5096,13 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, } } -#ifdef ENABLE_CLASSIC_FLANG +#ifndef ENABLE_CLASSIC_FLANG + Args.AddLastArg(CmdArgs, options::OPT_fveclib); +#else if (Args.getLastArg(options::OPT_fveclib)) Args.AddLastArg(CmdArgs, options::OPT_fveclib); else CmdArgs.push_back("-fveclib=PGMATH"); -#else - Args.AddLastArg(CmdArgs, options::OPT_fveclib); -#endif std::string PassRemarkVal(""), PassRemarkOpt(""); if (Args.getLastArg(options::OPT_Minfoall)) { @@ -5158,6 +5157,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-mllvm"); CmdArgs.push_back(Args.MakeArgString(PassRemarkOpt)); Args.ClaimAllArgs(options::OPT_Mneginfo_EQ); +#endif if (Args.hasFlag(options::OPT_fmerge_all_constants, options::OPT_fno_merge_all_constants, false)) diff --git a/clang/lib/Driver/ToolChains/ClassicFlang.cpp b/clang/lib/Driver/ToolChains/ClassicFlang.cpp index a68ec58e5e66..ba05861eab69 100644 --- a/clang/lib/Driver/ToolChains/ClassicFlang.cpp +++ b/clang/lib/Driver/ToolChains/ClassicFlang.cpp @@ -366,10 +366,10 @@ void ClassicFlang::ConstructJob(Compilation &C, const JobAction &JA, // Handle -fdefault-real-8 (and its alias, -r8) and -fno-default-real-8 if (Arg *A = Args.getLastArg(options::OPT_r8, options::OPT_fdefault_real_8, - options::OPT_default_real_8_fno)) { + options::OPT_fno_default_real_8)) { const char * fl; // For -f version add -x flag, for -fno add -y - if (A->getOption().matches(options::OPT_default_real_8_fno)) { + if (A->getOption().matches(options::OPT_fno_default_real_8)) { fl = "-y"; } else { fl = "-x"; @@ -377,7 +377,7 @@ void ClassicFlang::ConstructJob(Compilation &C, const JobAction &JA, for (Arg *A : Args.filtered(options::OPT_r8, options::OPT_fdefault_real_8, - options::OPT_default_real_8_fno)) { + options::OPT_fno_default_real_8)) { A->claim(); } @@ -392,10 +392,10 @@ void ClassicFlang::ConstructJob(Compilation &C, const JobAction &JA, // Process and claim -i8/-fdefault-integer-8/-fno-default-integer-8 argument if (Arg *A = Args.getLastArg(options::OPT_i8, options::OPT_fdefault_integer_8, - options::OPT_default_integer_8_fno)) { + options::OPT_fno_default_integer_8)) { const char * fl; - if (A->getOption().matches(options::OPT_default_integer_8_fno)) { + if (A->getOption().matches(options::OPT_fno_default_integer_8)) { fl = "-y"; } else { fl = "-x"; @@ -403,7 +403,7 @@ void ClassicFlang::ConstructJob(Compilation &C, const JobAction &JA, for (Arg *A : Args.filtered(options::OPT_i8, options::OPT_fdefault_integer_8, - options::OPT_default_integer_8_fno)) { + options::OPT_fno_default_integer_8)) { A->claim(); } @@ -727,14 +727,14 @@ void ClassicFlang::ConstructJob(Compilation &C, const JobAction &JA, default: llvm_unreachable("missed a case"); case options::OPT_ffixed_form: - case options::OPT_free_form_off: + case options::OPT_fno_free_form: case options::OPT_Mfixed: case options::OPT_Mfree_off: case options::OPT_Mfreeform_off: UpperCmdArgs.push_back("-nofreeform"); break; case options::OPT_ffree_form: - case options::OPT_fixed_form_off: + case options::OPT_fno_fixed_form: case options::OPT_Mfree_on: case options::OPT_Mfreeform_on: UpperCmdArgs.push_back("-freeform"); diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp index 84e9233a4aab..3c15cc014415 100644 --- a/clang/lib/Driver/ToolChains/CommonArgs.cpp +++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp @@ -120,6 +120,7 @@ static void renderRemarksHotnessOptions(const ArgList &Args, Twine("--plugin-opt=opt-remarks-hotness-threshold=") + A->getValue())); } +#ifdef ENABLE_CLASSIC_FLANG /// \brief Determine if Fortran "main" object is needed static bool needFortranMain(const Driver &D, const ArgList &Args) { return (needFortranLibs(D, Args) @@ -136,6 +137,7 @@ bool tools::needFortranLibs(const Driver &D, const ArgList &Args) { return false; } +#endif void tools::addPathIfExists(const Driver &D, const Twine &Path, ToolChain::path_list &Paths) { @@ -232,7 +234,9 @@ void tools::AddLinkerInputs(const ToolChain &TC, const InputInfoList &Inputs, const ArgList &Args, ArgStringList &CmdArgs, const JobAction &JA) { const Driver &D = TC.getDriver(); +#ifdef ENABLE_CLASSIC_FLANG bool SeenFirstLinkerInput = false; +#endif // Add extra linker input arguments which are not treated as inputs // (constructed via -Xarch_). @@ -266,6 +270,7 @@ void tools::AddLinkerInputs(const ToolChain &TC, const InputInfoList &Inputs, if (II.isNothing()) continue; +#ifdef ENABLE_CLASSIC_FLANG // Add Fortan "main" before the first linker input if (!SeenFirstLinkerInput) { if (needFortranMain(D, Args)) { @@ -273,7 +278,7 @@ void tools::AddLinkerInputs(const ToolChain &TC, const InputInfoList &Inputs, } SeenFirstLinkerInput = true; } - +#endif // Otherwise, this is a linker input argument. const Arg &A = II.getInputArg(); @@ -299,7 +304,7 @@ void tools::AddLinkerInputs(const ToolChain &TC, const InputInfoList &Inputs, A.renderAsInput(Args, CmdArgs); } } - +#ifdef ENABLE_CLASSIC_FLANG if (!SeenFirstLinkerInput && needFortranMain(D, Args)) { CmdArgs.push_back("-lflangmain"); } @@ -308,6 +313,7 @@ void tools::AddLinkerInputs(const ToolChain &TC, const InputInfoList &Inputs, for (auto Arg : Args.filtered(options::OPT_no_fortran_main, options::OPT_Mnomain)) { Arg->claim(); } +#endif } void tools::addLinkerCompressDebugSectionsOption( diff --git a/clang/lib/Driver/ToolChains/CommonArgs.h b/clang/lib/Driver/ToolChains/CommonArgs.h index 82ad2f387f08..d012f4ff8112 100644 --- a/clang/lib/Driver/ToolChains/CommonArgs.h +++ b/clang/lib/Driver/ToolChains/CommonArgs.h @@ -20,7 +20,9 @@ namespace clang { namespace driver { namespace tools { +#ifdef ENABLE_CLASSIC_FLANG bool needFortranLibs(const Driver &D, const llvm::opt::ArgList &Args); +#endif void addPathIfExists(const Driver &D, const Twine &Path, ToolChain::path_list &Paths); diff --git a/clang/lib/Driver/ToolChains/Cuda.cpp b/clang/lib/Driver/ToolChains/Cuda.cpp index 997b1e9ce7fc..4d7b6117809b 100644 --- a/clang/lib/Driver/ToolChains/Cuda.cpp +++ b/clang/lib/Driver/ToolChains/Cuda.cpp @@ -920,6 +920,7 @@ VersionTuple CudaToolChain::computeMSVCVersion(const Driver *D, return HostTC.computeMSVCVersion(D, Args); } +#ifdef ENABLE_CLASSIC_FLANG static void AddFlangSysIncludeArg(const ArgList &DriverArgs, ArgStringList &Flang1Args, ToolChain::path_list IncludePathList) { @@ -952,3 +953,4 @@ void CudaToolChain::AddFlangSystemIncludeArgs(const llvm::opt::ArgList &DriverAr IncludePathList.push_back(P.c_str()); AddFlangSysIncludeArg(DriverArgs, Flang1Args, IncludePathList); } +#endif diff --git a/clang/lib/Driver/ToolChains/Cuda.h b/clang/lib/Driver/ToolChains/Cuda.h index d860c7a433f6..04d2517ea2b3 100644 --- a/clang/lib/Driver/ToolChains/Cuda.h +++ b/clang/lib/Driver/ToolChains/Cuda.h @@ -184,6 +184,11 @@ public: llvm::opt::ArgStringList &CC1Args) const override; void AddIAMCUIncludeArgs(const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args) const override; +#ifdef ENABLE_CLASSIC_FLANG + void + AddFlangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs, + llvm::opt::ArgStringList &Flang1Args) const override; +#endif SanitizerMask getSupportedSanitizers() const override; @@ -198,9 +203,6 @@ public: const ToolChain &HostTC; CudaInstallationDetector CudaInstallation; - void - AddFlangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs, - llvm::opt::ArgStringList &Flang1Args) const override; protected: Tool *buildAssembler() const override; // ptxas Tool *buildLinker() const override; // fatbinary (ok, not really a linker) diff --git a/clang/lib/Driver/ToolChains/Gnu.cpp b/clang/lib/Driver/ToolChains/Gnu.cpp index 1c0800fdbc77..9d5707713210 100644 --- a/clang/lib/Driver/ToolChains/Gnu.cpp +++ b/clang/lib/Driver/ToolChains/Gnu.cpp @@ -567,6 +567,7 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA, // The profile runtime also needs access to system libraries. getToolChain().addProfileRTLibs(Args, CmdArgs); +#ifdef ENABLE_CLASSIC_FLANG // Add Fortran runtime libraries if (needFortranLibs(D, Args)) { ToolChain.AddFortranStdlibLibArgs(Args, CmdArgs); @@ -576,6 +577,7 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA, Arg->claim(); } } +#endif if (D.CCCIsCXX() && !Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs, diff --git a/clang/lib/Driver/ToolChains/Linux.cpp b/clang/lib/Driver/ToolChains/Linux.cpp index 23838ee992b2..992c6bd8ea8d 100644 --- a/clang/lib/Driver/ToolChains/Linux.cpp +++ b/clang/lib/Driver/ToolChains/Linux.cpp @@ -566,6 +566,7 @@ std::string Linux::getDynamicLinker(const ArgList &Args) const { return "/" + LibDir + "/" + Loader; } +#ifdef ENABLE_CLASSIC_FLANG /// Convert path list to Fortran frontend argument static void AddFlangSysIncludeArg(const ArgList &DriverArgs, ArgStringList &Flang1Args, @@ -753,6 +754,7 @@ void Linux::AddFlangSystemIncludeArgs(const ArgList &DriverArgs, AddFlangSysIncludeArg(DriverArgs, Flang1Args, IncludePathList); } +#endif void Linux::AddClangSystemIncludeArgs(const ArgList &DriverArgs, ArgStringList &CC1Args) const { diff --git a/clang/lib/Driver/ToolChains/Linux.h b/clang/lib/Driver/ToolChains/Linux.h index 58e8f0358305..59cf1498cd09 100644 --- a/clang/lib/Driver/ToolChains/Linux.h +++ b/clang/lib/Driver/ToolChains/Linux.h @@ -27,9 +27,11 @@ public: const llvm::Triple &TargetTriple, StringRef SysRoot) const override; +#ifdef ENABLE_CLASSIC_FLANG void AddFlangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &Flang1Args) const override; +#endif void AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args) const override; -- Gitee From fb14a769c1128088af2a3cb25748dc8f9ab4f047 Mon Sep 17 00:00:00 2001 From: Alok Kumar Sharma <60725621+alokkrsharma@users.noreply.github.com> Date: Sun, 20 Sep 2020 17:21:34 +0530 Subject: [PATCH 05/33] Support for DWARF 4/5 and fix of issues related to -gdwarf-X options (#92) * Support for -gdwarf-5 option in Flang driver. Summary: FLANG driver doesnt pass -gdwarf-4/5 to flang1 in form of xbits, while it passes for -gdwarf-2/3 -gdwarf-2 => -x 120 0x200 -gdwarf-3 => -x 120 0x4000 Due to this -gdwarf-5 is never honored and default option -gdwarf-4 is taken. # flang -gdwarf-5 test.f90 # llvm-dwarfdump a.out | grep version 0x00000000: Compile Unit: length = 0x0000008e version = 0x0004 Now 0x1000000/0x2000000 will be passed for -gdwarf-4/5 -gdwarf-4 => -x 120 0x1000000 -gdwarf-5 => -x 120 0x2000000 Testing: - GNU gdb fortran testsuite - check-llvm - check-debuginfo * Flang doenst choose correct dwarf version when multiple -g/-gdwarfN mentioned Summary: When multiple -g/-gdwarfN options are passed together at compile time, flang chooses the least one. Clang/gfortran etc choose the last one. -gdwarf-5 -gdwarf-3 => flang chooses 5 while clang/gfortran choose 3 -gdwarf-5 -g => flang choses the default while clang/gfortran choose 5 Testing: - check-llvm - check-debuginfo * Default dwarf version should be 4 for -g with flang Currently flang dumps dwarf version 2 for -g and 4 for absence of -g ------------------------- $ flang my.f90 $ llvm-dwarfdump a.out | grep version 0x00000000: Compile Unit: length = 0x0000003d version = 0x0004 abbr_offset = 0x0000 addr_size = 0x08 (next unit at 0x00000041) $ flang -g my.f90 $ llvm-dwarfdump a.out | grep version 0x00000000: Compile Unit: length = 0x00000047 version = 0x0002 abbr_offset = 0x0000 addr_size = 0x08 (next unit at 0x0000004b) ------------------------- It should be 4 for -g as it is the case with clang. --- clang/lib/Driver/ToolChains/ClassicFlang.cpp | 42 +++++++++++--------- 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/clang/lib/Driver/ToolChains/ClassicFlang.cpp b/clang/lib/Driver/ToolChains/ClassicFlang.cpp index ba05861eab69..f297989910c5 100644 --- a/clang/lib/Driver/ToolChains/ClassicFlang.cpp +++ b/clang/lib/Driver/ToolChains/ClassicFlang.cpp @@ -327,28 +327,34 @@ void ClassicFlang::ConstructJob(Compilation &C, const JobAction &JA, LowerCmdArgs.push_back("0x8"); } - // -g should produce DWARFv2 - for (auto Arg : Args.filtered(options::OPT_g_Flag)) { - Arg->claim(); - CommonCmdArgs.push_back("-x"); - CommonCmdArgs.push_back("120"); - CommonCmdArgs.push_back("0x200"); - } + // Last argument of -g/-gdwarfX should be taken. + Arg *GArg = Args.getLastArg(options::OPT_g_Flag); + Arg *GDwarfArg = Args.getLastArg(options::OPT_gdwarf_2, + options::OPT_gdwarf_3, + options::OPT_gdwarf_4, + options::OPT_gdwarf_5); + + if (GArg || GDwarfArg) { + + for (auto Arg : Args.filtered(options::OPT_g_Flag, options::OPT_gdwarf_2, + options::OPT_gdwarf_3, options::OPT_gdwarf_4, + options::OPT_gdwarf_5)) { + Arg->claim(); + } - // -gdwarf-2 - for (auto Arg : Args.filtered(options::OPT_gdwarf_2)) { - Arg->claim(); CommonCmdArgs.push_back("-x"); CommonCmdArgs.push_back("120"); - CommonCmdArgs.push_back("0x200"); - } - // -gdwarf-3 - for (auto Arg : Args.filtered(options::OPT_gdwarf_3)) { - Arg->claim(); - CommonCmdArgs.push_back("-x"); - CommonCmdArgs.push_back("120"); - CommonCmdArgs.push_back("0x4000"); + if (!GDwarfArg) // -g without -gdwarf-X produces default (DWARFv4) + CommonCmdArgs.push_back("0x1000000"); + else if (GDwarfArg->getOption().matches(options::OPT_gdwarf_2)) // -gdwarf-2 + CommonCmdArgs.push_back("0x200"); + else if (GDwarfArg->getOption().matches(options::OPT_gdwarf_3)) // -gdwarf-3 + CommonCmdArgs.push_back("0x4000"); + else if (GDwarfArg->getOption().matches(options::OPT_gdwarf_4)) // -gdwarf-4 + CommonCmdArgs.push_back("0x1000000"); + else if (GDwarfArg->getOption().matches(options::OPT_gdwarf_5)) // -gdwarf-5 + CommonCmdArgs.push_back("0x2000000"); } // -Mipa has no effect -- Gitee From 49d4fba77731705fc23a3e0b200f376a1b17c18d Mon Sep 17 00:00:00 2001 From: Bryan Chan Date: Mon, 12 Oct 2020 14:19:48 -0400 Subject: [PATCH 06/33] Reduce downstream delta This commit is motivated by reducing the merge burden by shrinking the diff between llvm upstream and classic-flang-llvm-project. Outside of Flang, Fortran code is fed through the Compile phase, and the appropriate tooling is picked up through ToolChain::SelectTool. Classic Flang introduced a FortranFrontend, but these days this seems unnecessary. Fortran can go through the same machinery as everything else. * Use the Preprocess phase to preprocess Fortran code. This phase is always combined with the Compile phase. * Use the Compile phase to lower Fortran code to LLVM IR, and use the Backend phase to compile and optimize the IR. These phases are never combined. * Remove FortranFrontendJobClass. * Remove FortranFrontend tool (instead it's just the Flang tool, which in Classic Flang mode is Classic Flang). * Update tests which inspect the output of the Classic Flang tooling, and ensures that the driver does the right thing for various types of inputs. Based on a patch from Peter Waller . --- clang/include/clang/Driver/Action.h | 11 ---- clang/include/clang/Driver/Phases.h | 1 - clang/include/clang/Driver/ToolChain.h | 2 - clang/include/clang/Driver/Types.def | 8 +-- clang/lib/Driver/Action.cpp | 7 --- clang/lib/Driver/Driver.cpp | 50 ++++++++----------- clang/lib/Driver/Phases.cpp | 1 - clang/lib/Driver/ToolChain.cpp | 21 ++------ clang/lib/Driver/ToolChains/ClassicFlang.h | 2 +- .../flang/classic-flang-must-preprocess.F | 12 +++++ .../flang/classic-flang-must-preprocess.F95 | 12 +++++ clang/test/Driver/flang/classic-flang.f | 26 ++++++++++ clang/test/Driver/flang/classic-flang.f95 | 43 ++++++++++++++++ clang/test/Driver/flang/classic_flang.f95 | 28 ----------- clang/test/Driver/lit.local.cfg | 1 + 15 files changed, 123 insertions(+), 102 deletions(-) create mode 100644 clang/test/Driver/flang/classic-flang-must-preprocess.F create mode 100644 clang/test/Driver/flang/classic-flang-must-preprocess.F95 create mode 100644 clang/test/Driver/flang/classic-flang.f create mode 100644 clang/test/Driver/flang/classic-flang.f95 delete mode 100644 clang/test/Driver/flang/classic_flang.f95 diff --git a/clang/include/clang/Driver/Action.h b/clang/include/clang/Driver/Action.h index b1a91edb6158..684ccd358275 100644 --- a/clang/include/clang/Driver/Action.h +++ b/clang/include/clang/Driver/Action.h @@ -63,7 +63,6 @@ public: AnalyzeJobClass, MigrateJobClass, CompileJobClass, - FortranFrontendJobClass, BackendJobClass, AssembleJobClass, LinkJobClass, @@ -488,16 +487,6 @@ public: } }; -class FortranFrontendJobAction : public JobAction { - void anchor() override; -public: - FortranFrontendJobAction(Action *Input, types::ID OutputType); - - static bool classof(const Action *A) { - return A->getKind() == FortranFrontendJobClass; - } -}; - class CompileJobAction : public JobAction { void anchor() override; diff --git a/clang/include/clang/Driver/Phases.h b/clang/include/clang/Driver/Phases.h index f8cac9548d02..9003c5857351 100644 --- a/clang/include/clang/Driver/Phases.h +++ b/clang/include/clang/Driver/Phases.h @@ -17,7 +17,6 @@ namespace phases { enum ID { Preprocess, Precompile, - FortranFrontend, Compile, Backend, Assemble, diff --git a/clang/include/clang/Driver/ToolChain.h b/clang/include/clang/Driver/ToolChain.h index 842e93b3a09c..6f48088b3662 100644 --- a/clang/include/clang/Driver/ToolChain.h +++ b/clang/include/clang/Driver/ToolChain.h @@ -145,7 +145,6 @@ private: mutable std::unique_ptr Clang; mutable std::unique_ptr Flang; - mutable std::unique_ptr FortranFrontend; mutable std::unique_ptr Assemble; mutable std::unique_ptr Link; mutable std::unique_ptr StaticLibTool; @@ -157,7 +156,6 @@ private: Tool *getClang() const; Tool *getFlang() const; - Tool *getFortranFrontend() const; Tool *getAssemble() const; Tool *getLink() const; Tool *getStaticLibTool() const; diff --git a/clang/include/clang/Driver/Types.def b/clang/include/clang/Driver/Types.def index 7f91e348d875..8b5b3b9d6eb9 100644 --- a/clang/include/clang/Driver/Types.def +++ b/clang/include/clang/Driver/Types.def @@ -78,10 +78,10 @@ TYPE("ada", Ada, INVALID, nullptr, phases TYPE("assembler", PP_Asm, INVALID, "s", phases::Assemble, phases::Link) TYPE("assembler-with-cpp", Asm, PP_Asm, "S", phases::Preprocess, phases::Assemble, phases::Link) #ifdef ENABLE_CLASSIC_FLANG -TYPE("f77", PP_F_FixedForm, INVALID, "f", phases::FortranFrontend, phases::Backend, phases::Assemble, phases::Link) -TYPE("f77-cpp-input", F_FixedForm, PP_F_FixedForm, "F", phases::FortranFrontend, phases::Backend, phases::Assemble, phases::Link) -TYPE("f95", PP_F_FreeForm, INVALID, "f95", phases::FortranFrontend, phases::Backend, phases::Assemble, phases::Link) -TYPE("f95-cpp-input", F_FreeForm, PP_F_FreeForm, "F95", phases::FortranFrontend, phases::Backend, phases::Assemble, phases::Link) +TYPE("f77", PP_F_FixedForm, INVALID, "f", phases::Compile, phases::Backend, phases::Assemble, phases::Link) +TYPE("f77-cpp-input", F_FixedForm, PP_F_FixedForm, "F", phases::Preprocess, phases::Compile, phases::Backend, phases::Assemble, phases::Link) +TYPE("f95", PP_F_FreeForm, INVALID, "f95", phases::Compile, phases::Backend, phases::Assemble, phases::Link) +TYPE("f95-cpp-input", F_FreeForm, PP_F_FreeForm, "F95", phases::Preprocess, phases::Compile, phases::Backend, phases::Assemble, phases::Link) #else TYPE("f95", PP_Fortran, INVALID, "i", phases::Compile, phases::Backend, phases::Assemble, phases::Link) TYPE("f95-cpp-input", Fortran, PP_Fortran, nullptr, phases::Preprocess, phases::Compile, phases::Backend, phases::Assemble, phases::Link) diff --git a/clang/lib/Driver/Action.cpp b/clang/lib/Driver/Action.cpp index d77b525cd8b0..ead3a23da418 100644 --- a/clang/lib/Driver/Action.cpp +++ b/clang/lib/Driver/Action.cpp @@ -30,7 +30,6 @@ const char *Action::getClassName(ActionClass AC) { return "api-extractor"; case AnalyzeJobClass: return "analyzer"; case MigrateJobClass: return "migrator"; - case FortranFrontendJobClass: return "fortran-frontend"; case CompileJobClass: return "compiler"; case BackendJobClass: return "backend"; case AssembleJobClass: return "assembler"; @@ -364,12 +363,6 @@ void MigrateJobAction::anchor() {} MigrateJobAction::MigrateJobAction(Action *Input, types::ID OutputType) : JobAction(MigrateJobClass, Input, OutputType) {} -void FortranFrontendJobAction::anchor() {} - -FortranFrontendJobAction::FortranFrontendJobAction(Action *Input, - types::ID OutputType) - : JobAction(FortranFrontendJobClass, Input, OutputType) {} - void CompileJobAction::anchor() {} CompileJobAction::CompileJobAction(Action *Input, types::ID OutputType) diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp index e5a4aa955f63..8fc5d09437f6 100644 --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -333,27 +333,15 @@ phases::ID Driver::getFinalPhase(const DerivedArgList &DAL, // -{E,EP,P,M,MM} only run the preprocessor. if (CCCIsCPP() || (PhaseArg = DAL.getLastArg(options::OPT_E)) || -#ifdef ENABLE_CLASSIC_FLANG - (PhaseArg = DAL.getLastArg(options::OPT_fsyntax_only)) || -#endif (PhaseArg = DAL.getLastArg(options::OPT__SLASH_EP)) || (PhaseArg = DAL.getLastArg(options::OPT_M, options::OPT_MM)) || (PhaseArg = DAL.getLastArg(options::OPT__SLASH_P)) || CCGenDiagnostics) { #ifdef ENABLE_CLASSIC_FLANG - // -fsyntax-only or -E stops Fortran compilation after FortranFrontend - if (IsFlangMode() && (DAL.getLastArg(options::OPT_E) || - DAL.getLastArg(options::OPT_fsyntax_only))) { - FinalPhase = phases::FortranFrontend; - - // if not Fortran, fsyntax_only implies 'Compile' is the FinalPhase - } else if (DAL.getLastArg(options::OPT_fsyntax_only)) { + if (IsFlangMode()) FinalPhase = phases::Compile; - - // everything else has 'Preprocess' as its FinalPhase - } else { + else FinalPhase = phases::Preprocess; - } #else FinalPhase = phases::Preprocess; #endif @@ -367,14 +355,9 @@ phases::ID Driver::getFinalPhase(const DerivedArgList &DAL, options::OPT_fmodule_header_EQ))) { FinalPhase = phases::Precompile; -#ifdef ENABLE_CLASSIC_FLANG - // -{analyze,emit-ast} only run up to the compiler. - } else if ((PhaseArg = DAL.getLastArg(options::OPT_print_supported_cpus)) || -#else // -{fsyntax-only,-analyze,emit-ast} only run up to the compiler. } else if ((PhaseArg = DAL.getLastArg(options::OPT_fsyntax_only)) || (PhaseArg = DAL.getLastArg(options::OPT_print_supported_cpus)) || -#endif (PhaseArg = DAL.getLastArg(options::OPT_module_file_info)) || (PhaseArg = DAL.getLastArg(options::OPT_verify_pch)) || (PhaseArg = DAL.getLastArg(options::OPT_rewrite_objc)) || @@ -3967,10 +3950,13 @@ void Driver::handleArguments(Compilation &C, DerivedArgList &Args, if (InputArg->isClaimed()) continue; - // Fortran input is preprocessed using the frontend. - if (InitialPhase == phases::FortranFrontend && +#ifdef ENABLE_CLASSIC_FLANG + // If the input is detected as already preprocessed (e.g. has the .f95 + // extension), and the user specifies -E, preprocess the file anyway. + if (IsFlangMode() && InitialPhase == phases::Compile && FinalPhase == phases::Preprocess) continue; +#endif // Claim here to avoid the more general unused warning. InputArg->claim(); @@ -4641,13 +4627,6 @@ Action *Driver::ConstructPhaseAction( ModName); return C.MakeAction(Input, OutputTy); } - case phases::FortranFrontend: { - if (Args.hasArg(options::OPT_fsyntax_only)) - return C.MakeAction(Input, - types::TY_Nothing); - return C.MakeAction(Input, - types::TY_LLVM_IR); - } case phases::Compile: { if (Args.hasArg(options::OPT_fsyntax_only)) return C.MakeAction(Input, types::TY_Nothing); @@ -4668,6 +4647,10 @@ Action *Driver::ConstructPhaseAction( return C.MakeAction(Input, types::TY_Nothing); if (Args.hasArg(options::OPT_extract_api)) return C.MakeAction(Input, types::TY_API_INFO); +#ifdef ENABLE_CLASSIC_FLANG + if (IsFlangMode()) + return C.MakeAction(Input, types::TY_LLVM_IR); +#endif return C.MakeAction(Input, types::TY_LLVM_BC); } case phases::Backend: { @@ -5096,6 +5079,10 @@ class ToolSelector final { if (!T->hasIntegratedBackend() && !(OutputIsLLVM && T->canEmitIR())) return nullptr; + // Classic Flang is not integrated with the backend. + if (C.getDriver().IsFlangMode() && !T->hasIntegratedAssembler()) + return nullptr; + if (T->canEmitIR() && ((SaveTemps && !InputIsBitcode) || EmbedBitcode)) return nullptr; @@ -6234,8 +6221,11 @@ bool Driver::ShouldUseFlangCompiler(const JobAction &JA) const { return false; // And say "no" if this is not a kind of action flang understands. - if (!isa(JA) && !isa(JA) && - !isa(JA)) + if (!isa(JA) && !isa(JA) +#ifndef ENABLE_CLASSIC_FLANG + && !isa(JA) +#endif + ) return false; return true; diff --git a/clang/lib/Driver/Phases.cpp b/clang/lib/Driver/Phases.cpp index f0216c5ab7c2..01598c59bd9e 100644 --- a/clang/lib/Driver/Phases.cpp +++ b/clang/lib/Driver/Phases.cpp @@ -16,7 +16,6 @@ const char *phases::getPhaseName(ID Id) { switch (Id) { case Preprocess: return "preprocessor"; case Precompile: return "precompiler"; - case FortranFrontend: return "fortran-frontend"; case Compile: return "compiler"; case Backend: return "backend"; case Assemble: return "assembler"; diff --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp index 87f4e670daa2..4dd7263bb30b 100644 --- a/clang/lib/Driver/ToolChain.cpp +++ b/clang/lib/Driver/ToolChain.cpp @@ -299,13 +299,13 @@ Tool *ToolChain::getClang() const { } Tool *ToolChain::getFlang() const { -#ifndef ENABLE_CLASSIC_FLANG if (!Flang) - Flang.reset(new tools::Flang(*this)); - return Flang.get(); +#ifdef ENABLE_CLASSIC_FLANG + Flang.reset(new tools::ClassicFlang(*this)); #else - llvm_unreachable("Flang is not supported by this toolchain"); + Flang.reset(new tools::Flang(*this)); #endif + return Flang.get(); } Tool *ToolChain::buildAssembler() const { @@ -326,16 +326,6 @@ Tool *ToolChain::getAssemble() const { return Assemble.get(); } -Tool *ToolChain::getFortranFrontend() const { -#ifdef ENABLE_CLASSIC_FLANG - if (!FortranFrontend) - FortranFrontend.reset(new tools::ClassicFlang(*this)); - return FortranFrontend.get(); -#else - llvm_unreachable("Fortran is not supported by this toolchain"); -#endif -} - Tool *ToolChain::getClangAs() const { if (!Assemble) Assemble.reset(new tools::ClangAs(*this)); @@ -427,9 +417,6 @@ Tool *ToolChain::getTool(Action::ActionClass AC) const { return getOffloadPackager(); case Action::LinkerWrapperJobClass: return getLinkerWrapper(); - - case Action::FortranFrontendJobClass: - return getFortranFrontend(); } llvm_unreachable("Invalid tool kind."); diff --git a/clang/lib/Driver/ToolChains/ClassicFlang.h b/clang/lib/Driver/ToolChains/ClassicFlang.h index 23ea1fe6b95d..5af119c2f79e 100644 --- a/clang/lib/Driver/ToolChains/ClassicFlang.h +++ b/clang/lib/Driver/ToolChains/ClassicFlang.h @@ -33,7 +33,7 @@ public: bool hasGoodDiagnostics() const override { return true; } bool hasIntegratedAssembler() const override { return false; } - bool hasIntegratedCPP() const override { return false; } + bool hasIntegratedCPP() const override { return true; } void ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, diff --git a/clang/test/Driver/flang/classic-flang-must-preprocess.F b/clang/test/Driver/flang/classic-flang-must-preprocess.F new file mode 100644 index 000000000000..d52c1cf8d3c0 --- /dev/null +++ b/clang/test/Driver/flang/classic-flang-must-preprocess.F @@ -0,0 +1,12 @@ +! REQUIRES: classic_flang + +! Check that the driver invokes flang1 correctly for fixed-form Fortran code +! which requires preprocessing. + +! RUN: %clang --driver-mode=flang -target x86_64-unknown-linux-gnu -c %s -### 2>&1 \ +! RUN: | FileCheck %s +! CHECK: "flang1" +! CHECK-SAME: "-preprocess" +! CHECK-SAME: "-nofreeform" +! CHECK-NEXT: "flang2" +! CHECK-NEXT: {{clang.* "-cc1"}} diff --git a/clang/test/Driver/flang/classic-flang-must-preprocess.F95 b/clang/test/Driver/flang/classic-flang-must-preprocess.F95 new file mode 100644 index 000000000000..7d452a535784 --- /dev/null +++ b/clang/test/Driver/flang/classic-flang-must-preprocess.F95 @@ -0,0 +1,12 @@ +! REQUIRES: classic_flang + +! Check that the driver invokes flang1 correctly for free-form Fortran code +! which requires preprocessing. + +! RUN: %clang --driver-mode=flang -target x86_64-unknown-linux-gnu -c %s -### 2>&1 \ +! RUN: | FileCheck %s +! CHECK: "flang1" +! CHECK-SAME: "-preprocess" +! CHECK-SAME: "-freeform" +! CHECK-NEXT: "flang2" +! CHECK-NEXT: {{clang.* "-cc1"}} diff --git a/clang/test/Driver/flang/classic-flang.f b/clang/test/Driver/flang/classic-flang.f new file mode 100644 index 000000000000..98f74d9626d7 --- /dev/null +++ b/clang/test/Driver/flang/classic-flang.f @@ -0,0 +1,26 @@ +! REQUIRES: classic_flang + +! Check that the driver invokes flang1 correctly for preprocessed fixed-form +! Fortran code. + +! RUN: %clang --driver-mode=flang -target x86_64-unknown-linux-gnu -c %s -### 2>&1 \ +! RUN: | FileCheck %s +! CHECK: "flang1" +! CHECK-NOT: "-preprocess" +! CHECK-SAME: "-nofreeform" +! CHECK-NEXT: "flang2" +! CHECK-NEXT: {{clang.* "-cc1"}} + +! Check that the driver invokes flang1 correctly when preprocessing is +! explicitly requested. + +! RUN: %clang --driver-mode=flang -target x86_64-unknown-linux-gnu -E %s -### 2>&1 \ +! RUN: | FileCheck --check-prefix=CHECK-PREPROCESS %s +! CHECK-PREPROCESS: "flang1" +! CHECK-PREPROCESS-SAME: "-preprocess" +! CHECK-PREPROCESS-SAME: "-es" +! CHECK-PREPROCESS-SAME: "-pp" +! CHECK-PREPROCESS-NOT: "flang1" +! CHECK-PREPROCESS-NOT: "flang2" +! CHECK-PREPROCESS-NOT: {{clang.* "-cc1"}} +! CHECK-PREPROCESS-NOT: {{clang.* "-cc1as"}} diff --git a/clang/test/Driver/flang/classic-flang.f95 b/clang/test/Driver/flang/classic-flang.f95 new file mode 100644 index 000000000000..0b92c799392a --- /dev/null +++ b/clang/test/Driver/flang/classic-flang.f95 @@ -0,0 +1,43 @@ +! REQUIRES: classic_flang + +! Check that the driver invokes flang1 correctly for preprocessed free-form +! Fortran code. Also check that the backend is invoked correctly. + +! RUN: %clang --driver-mode=flang -target x86_64-unknown-linux-gnu -c %s -### 2>&1 \ +! RUN: | FileCheck --check-prefix=CHECK-OBJECT %s +! CHECK-OBJECT: "flang1" +! CHECK-OBJECT-NOT: "-preprocess" +! CHECK-OBJECT-SAME: "-freeform" +! CHECK-OBJECT-NEXT: "flang2" +! CHECK-OBJECT-SAME: "-asm" [[LLFILE:.*.ll]] +! CHECK-OBJECT-NEXT: {{clang.* "-cc1"}} +! CHECK-OBJECT-SAME: "-o" "classic-flang.o" +! CHECK-OBJECT-SAME: "-x" "ir" +! CHECK-OBJECT-SAME: [[LLFILE]] + +! Check that the driver invokes flang1 correctly when preprocessing is +! explicitly requested. + +! RUN: %clang --driver-mode=flang -target x86_64-unknown-linux-gnu -E %s -### 2>&1 \ +! RUN: | FileCheck --check-prefix=CHECK-PREPROCESS %s +! CHECK-PREPROCESS: "flang1" +! CHECK-PREPROCESS-SAME: "-preprocess" +! CHECK-PREPROCESS-SAME: "-es" +! CHECK-PREPROCESS-SAME: "-pp" +! CHECK-PREPROCESS-NOT: "flang1" +! CHECK-PREPROCESS-NOT: "flang2" +! CHECK-PREPROCESS-NOT: {{clang.* "-cc1"}} +! CHECK-PREPROCESS-NOT: {{clang.* "-cc1as"}} + +! Check that the backend job (clang -cc1) is not combined into the compile job +! (flang2) even if -integrated-as is specified. + +! RUN: %clang --driver-mode=flang -target x86_64-unknown-linux-gnu -integrated-as -S %s -### 2>&1 \ +! RUN: | FileCheck --check-prefix=CHECK-ASM %s +! CHECK-ASM: "flang1" +! CHECK-ASM-NEXT: "flang2" +! CHECK-ASM-SAME: "-asm" [[LLFILE:.*.ll]] +! CHECK-ASM-NEXT: {{clang.* "-cc1"}} +! CHECK-ASM-SAME: "-o" "classic-flang.s" +! CHECK-ASM-SAME: "-x" "ir" +! CHECK-ASM-SAME: [[LLFILE]] diff --git a/clang/test/Driver/flang/classic_flang.f95 b/clang/test/Driver/flang/classic_flang.f95 deleted file mode 100644 index 5d3098786905..000000000000 --- a/clang/test/Driver/flang/classic_flang.f95 +++ /dev/null @@ -1,28 +0,0 @@ -! Check that the driver can invoke flang1 and flang2 to compile Fortran with -! --driver-mode=flang (default when the file extension is .f95). - -! REQUIRES: classic_flang - -! RUN: %clang -target x86_64-unknown-linux-gnu -integrated-as -c %s -### 2>&1 \ -! RUN: | FileCheck --check-prefix=CHECK-OBJECT %s -! CHECK-OBJECT: flang1 -! CHECK-OBJECT: flang2 -! CHECK-OBJECT-SAME: "-asm" [[LLFILE:.*.ll]] -! CHECK-OBJECT-NOT: cc1as -! CHECK-OBJECT: clang -! CHECK-OBJECT-SAME: -cc1 -! CHECK-OBJECT-SAME: "-o" "classic_flang.o" -! CHECK-OBJECT-SAME: "-x" "ir" -! CHECK-OBJECT-SAME: [[LLFILE]] - -! RUN: %clang -target x86_64-unknown-linux-gnu -integrated-as -S %s -### 2>&1 \ -! RUN: | FileCheck --check-prefix=CHECK-ASM %s -! CHECK-ASM: flang1 -! CHECK-ASM: flang2 -! CHECK-ASM-SAME: "-asm" [[LLFILE:.*.ll]] -! CHECK-ASM-NOT: cc1as -! CHECK-ASM: clang -! CHECK-ASM-SAME: -cc1 -! CHECK-ASM-SAME: "-o" "classic_flang.s" -! CHECK-ASM-SAME: "-x" "ir" -! CHECK-ASM-SAME: [[LLFILE]] diff --git a/clang/test/Driver/lit.local.cfg b/clang/test/Driver/lit.local.cfg index 671d9a4b1873..b701be566d5d 100644 --- a/clang/test/Driver/lit.local.cfg +++ b/clang/test/Driver/lit.local.cfg @@ -1,4 +1,5 @@ config.suffixes = ['.c', '.cpp', '.h', '.m', '.mm', '.S', '.s', '.f90', '.F90', '.f95', + '.F95', '.f', '.F', '.cu', '.rs', '.cl', '.clcpp', '.hip', '.hlsl'] config.substitutions = list(config.substitutions) config.substitutions.insert(0, -- Gitee From 157db53d9a8c1474c78258608ec5c5d48d5490de Mon Sep 17 00:00:00 2001 From: Kiran Chandramohan Date: Wed, 28 Oct 2020 17:08:22 +0000 Subject: [PATCH 07/33] [workflows] Set up GitHub actions for Classic Flang This commit squashes the following CI-related patches from the release_14x branch. commit 54a96d02d32f678633b3e05c4db490bfd8ec3745 Author: Kiran Chandramohan Date: Mon May 2 21:16:56 2022 -0400 [workflows] Stop using upstream actions and enable OpenMP build commit b921dd2acf4c0171ffa70c566306ba6ac1e99925 Author: michalpasztamobica Date: Fri Jun 4 13:55:52 2021 +0200 [workflows] Allow pre-compile jobs to be trigerred manually. commit 9f828fd21877085faeba914b65957945cca319e4 Author: michalpasztamobica Date: Fri Jun 4 22:09:44 2021 +0200 [workflows] Add build scripts and make CI use them. commit a976b9665c33f5b2902e79a1caaca8db8d5adc02 Author: Abraham Tovar Date: Wed Oct 13 11:40:30 2021 +0200 [workflows] LLVM release_13x CI changes commit 7a5ee225b6d5926649408e39a919d5a25cf0b759 Author: Abraham Tovar Date: Wed Nov 17 10:14:21 2021 +0000 [workflows] Removing CI test-base for release_100 commit a39a0c662d6f49a41cdfa5f23f9b5ea521bcd1e6 Author: pwisniewskimobica Date: Thu Jan 27 15:06:19 2022 +0100 [workflows] Use GCC 11 in CI builds commit 198a6b22ac62ed10e639d9e734059172a226454a Author: pwisniewskimobica Date: Thu Jan 13 10:11:43 2022 +0100 [workflows] Modify CI scripts to add more test variants commit 84ed34d208d84a30ba4ccae93c30444561d6180f Author: Bryan Chan Date: Sun Apr 24 19:13:25 2022 -0400 [workflows] support GitHub actions for release_14x branch commit dd852a697f1a86edc67184e8809ef9a12e965608 Author: Bryan Chan Date: Fri Jul 15 21:50:21 2022 -0400 [workflows] Fix CI for release_14x commit b52bcc04b83d00284f47086bc0843e2fbe489fed Author: Bryan Chan Date: Wed Jul 27 22:28:43 2022 -0400 [build] Stop caching AArch64 Docker image layers --- .github/workflows/clang-tests.yml | 6 +- .github/workflows/flang-tests.yml | 80 +++++++++ .github/workflows/libclang-abi-tests.yml | 166 ------------------ .github/workflows/libclc-tests.yml | 39 ---- .github/workflows/lld-tests.yml | 37 ---- .github/workflows/lldb-tests.yml | 40 ----- .github/workflows/llvm-project-tests.yml | 33 ++-- .github/workflows/llvm-tests.yml | 165 +---------------- .github/workflows/pre-compile_llvm.yml | 80 +++++++++ .github/workflows/repo-lockdown.yml | 19 -- build-llvm-project.sh | 94 ++++++++++ .../flang/classic-flang-must-preprocess.F | 4 +- .../flang/classic-flang-must-preprocess.F95 | 4 +- clang/test/Driver/flang/classic-flang.f | 10 +- clang/test/Driver/flang/classic-flang.f95 | 14 +- 15 files changed, 291 insertions(+), 500 deletions(-) create mode 100644 .github/workflows/flang-tests.yml delete mode 100644 .github/workflows/libclang-abi-tests.yml delete mode 100644 .github/workflows/libclc-tests.yml delete mode 100644 .github/workflows/lld-tests.yml delete mode 100644 .github/workflows/lldb-tests.yml create mode 100644 .github/workflows/pre-compile_llvm.yml delete mode 100644 .github/workflows/repo-lockdown.yml create mode 100755 build-llvm-project.sh diff --git a/.github/workflows/clang-tests.yml b/.github/workflows/clang-tests.yml index fb2d04b3b30c..f8d5fd8f4666 100644 --- a/.github/workflows/clang-tests.yml +++ b/.github/workflows/clang-tests.yml @@ -29,9 +29,9 @@ concurrency: jobs: check_clang: - if: github.repository_owner == 'llvm' - name: Test clang,lldb,libclc + if: github.repository_owner == 'flang-compiler' + name: Test clang uses: ./.github/workflows/llvm-project-tests.yml with: build_target: check-clang - projects: clang;lldb;libclc + projects: clang;openmp diff --git a/.github/workflows/flang-tests.yml b/.github/workflows/flang-tests.yml new file mode 100644 index 000000000000..410ba05290a7 --- /dev/null +++ b/.github/workflows/flang-tests.yml @@ -0,0 +1,80 @@ +name: Build and test Flang + +on: + pull_request: + branches: [ release_11x, release_12x, release_13x, release_14x ] + +jobs: + build: + runs-on: ubuntu-20.04 + env: + install_prefix: /usr/local + strategy: + matrix: + target: [X86] + cc: [clang] + cpp: [clang++] + version: [10, 11] + include: + - target: X86 + cc: gcc + cpp: g++ + version: 10 + + steps: + - uses: actions/checkout@v2 + + - if: matrix.cc == 'clang' + run: | + sudo add-apt-repository ppa:ubuntu-toolchain-r/ppa + sudo touch /etc/apt/sources.list.d/llvm.list + echo 'deb http://apt.llvm.org/focal/ llvm-toolchain-focal-11 main' | sudo tee -a /etc/apt/sources.list.d/llvm.list + echo 'deb-src http://apt.llvm.org/focal/ llvm-toolchain-focal-11 main' | sudo tee -a /etc/apt/sources.list.d/llvm.list + wget -q -O - http://apt.llvm.org/llvm-snapshot.gpg.key|sudo apt-key add - + sudo apt update + sudo apt install -f -y llvm-${{ matrix.version }} clang-${{ matrix.version}} + + - if: matrix.cc == 'gcc' && matrix.version == '10' + run: | + sudo add-apt-repository ppa:ubuntu-toolchain-r/ppa + sudo apt install gcc-10 g++-10 + sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-9 10 + sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-10 20 + sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-9 10 + sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-10 20 + + - name: ccache + uses: hendrikmuhs/ccache-action@v1 + with: + key: key-${{ matrix.cc }}-${{ matrix.version }} + + - name: Check tools + run: | + git --version + cmake --version + make --version + ${{ matrix.cc }}-${{ matrix.version }} --version + ${{ matrix.cpp }}-${{ matrix.version }} --version + + - name: Build and install llvm + run: ./build-llvm-project.sh -t ${{ matrix.target }} -p ${{ env.install_prefix }} -a /usr/bin/${{ matrix.cc }}-${{ matrix.version }} -b /usr/bin/${{ matrix.cpp }}-${{ matrix.version }} -n $(nproc) -c -i -s -v + + - name: Checkout flang + run: | + cd ../.. + git clone --depth 1 --single-branch --branch master https://github.com/flang-compiler/flang.git + + - name: Build and install libpgmath & flang + run: | + cd ../../flang + ./build-flang.sh -t ${{ matrix.target }} -p ${{ env.install_prefix }} -n $(nproc) -c -s + + - name: Copy llvm-lit + run: | + cd ../../flang + cp ../classic-flang-llvm-project/classic-flang-llvm-project/build/bin/llvm-lit build/bin/. + + - name: Test flang + run: | + cd ../../flang/build + make check-all diff --git a/.github/workflows/libclang-abi-tests.yml b/.github/workflows/libclang-abi-tests.yml deleted file mode 100644 index 8cc2f3a0fa3f..000000000000 --- a/.github/workflows/libclang-abi-tests.yml +++ /dev/null @@ -1,166 +0,0 @@ -name: libclang ABI Tests - -on: - workflow_dispatch: - push: - ignore-forks: true - branches: - - 'release/**' - paths: - - 'clang/**' - - '.github/workflows/libclang-abi-tests.yml' - pull_request: - ignore-forks: true - branches: - - 'release/**' - paths: - - 'clang/**' - - '.github/workflows/libclang-abi-tests.yml' - -concurrency: - # Skip intermediate builds: always. - # Cancel intermediate builds: only if it is a pull request build. - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: ${{ startsWith(github.ref, 'refs/pull/') }} - - -jobs: - abi-dump-setup: - if: github.repository_owner == 'llvm' - runs-on: ubuntu-latest - outputs: - BASELINE_REF: ${{ steps.vars.outputs.BASELINE_REF }} - ABI_HEADERS: ${{ steps.vars.outputs.ABI_HEADERS }} - ABI_LIBS: ${{ steps.vars.outputs.ABI_LIBS }} - BASELINE_VERSION_MAJOR: ${{ steps.vars.outputs.BASELINE_VERSION_MAJOR }} - BASELINE_VERSION_MINOR: ${{ steps.vars.outputs.BASELINE_VERSION_MINOR }} - LLVM_VERSION_MAJOR: ${{ steps.version.outputs.LLVM_VERSION_MAJOR }} - LLVM_VERSION_MINOR: ${{ steps.version.outputs.LLVM_VERSION_MINOR }} - LLVM_VERSION_PATCH: ${{ steps.version.outputs.LLVM_VERSION_PATCH }} - steps: - - name: Checkout source - uses: actions/checkout@v3 - with: - fetch-depth: 250 - - - name: Get LLVM version - id: version - uses: llvm/actions/get-llvm-version@main - - - name: Setup Variables - id: vars - run: | - minor_version=0 - remote_repo='https://github.com/llvm/llvm-project' - if [ ${{ steps.version.outputs.LLVM_VERSION_MINOR }} -ne 0 -o ${{ steps.version.outputs.LLVM_VERSION_PATCH }} -eq 0 ]; then - major_version=$(( ${{ steps.version.outputs.LLVM_VERSION_MAJOR }} - 1)) - baseline_ref="llvmorg-$major_version.0.0" - - # If there is a minor release, we want to use that as the base line. - minor_ref=`git ls-remote --refs -t $remote_repo llvmorg-$major_version.[1-9].[0-9] | tail -n1 | grep -o 'llvmorg-.\+' || true` - if [ -n "$minor_ref" ]; then - baseline_ref=$minor_ref - else - # Check if we have a release candidate - rc_ref=`git ls-remote --refs -t $remote_repo llvmorg-$major_version.[1-9].[0-9]-rc* | tail -n1 | grep -o 'llvmorg-.\+' || true` - if [ -n "$rc_ref" ]; then - baseline_ref=$rc_ref - fi - fi - echo ::set-output name=BASELINE_VERSION_MAJOR::$major_version - echo ::set-output name=BASELINE_REF::$baseline_ref - echo ::set-output name=ABI_HEADERS::clang-c - echo ::set-output name=ABI_LIBS::libclang.so - else - echo ::set-output name=BASELINE_VERSION_MAJOR::${{ steps.version.outputs.LLVM_VERSION_MAJOR }} - echo ::set-output name=BASELINE_REF::llvmorg-${{ steps.version.outputs.LLVM_VERSION_MAJOR }}.0.0 - echo ::set-output name=ABI_HEADERS::. - echo ::set-output name=ABI_LIBS::libclang.so libclang-cpp.so - fi - - - abi-dump: - if: github.repository_owner == 'llvm' - needs: abi-dump-setup - runs-on: ubuntu-latest - strategy: - matrix: - name: - - build-baseline - - build-latest - include: - - name: build-baseline - llvm_version_major: ${{ needs.abi-dump-setup.outputs.BASELINE_VERSION_MAJOR }} - ref: ${{ needs.abi-dump-setup.outputs.BASELINE_REF }} - repo: llvm/llvm-project - - name: build-latest - llvm_version_major: ${{ needs.abi-dump-setup.outputs.LLVM_VERSION_MAJOR }} - ref: ${{ github.sha }} - repo: ${{ github.repository }} - steps: - - name: Install Ninja - uses: llvm/actions/install-ninja@main - - name: Install abi-compliance-checker - run: | - sudo apt-get install abi-dumper autoconf pkg-config - - name: Install universal-ctags - run: | - git clone https://github.com/universal-ctags/ctags.git - cd ctags - ./autogen.sh - ./configure - sudo make install - - name: Download source code - uses: llvm/actions/get-llvm-project-src@main - with: - ref: ${{ matrix.ref }} - repo: ${{ matrix.repo }} - - name: Configure - run: | - mkdir install - cmake -B build -S llvm -G Ninja -DLLVM_ENABLE_PROJECTS=clang -DCMAKE_BUILD_TYPE=Debug -DLLVM_TARGETS_TO_BUILD="" -DLLVM_BUILD_LLVM_DYLIB=ON -DLLVM_LINK_LLVM_DYLIB=ON -DCMAKE_C_FLAGS_DEBUG="-g1 -Og" -DCMAKE_CXX_FLAGS_DEBUG="-g1 -Og" -DCMAKE_INSTALL_PREFIX=`pwd`/install llvm - - name: Build - run: ninja -C build/ ${{ needs.abi-dump-setup.outputs.ABI_LIBS }} install-clang-headers - - name: Dump ABI - run: | - parallel abi-dumper -lver ${{ matrix.ref }} -skip-cxx -public-headers ./install/include/${{ needs.abi-dump-setup.outputs.ABI_HEADERS }} -o {}-${{ matrix.ref }}.abi ./build/lib/{} ::: ${{ needs.abi-dump-setup.outputs.ABI_LIBS }} - for lib in ${{ needs.abi-dump-setup.outputs.ABI_LIBS }}; do - # Remove symbol versioning from dumps, so we can compare across major versions. - sed -i 's/LLVM_[0-9]\+/LLVM_NOVERSION/' $lib-${{ matrix.ref }}.abi - done - - name: Upload ABI file - uses: actions/upload-artifact@v2 - with: - name: ${{ matrix.name }} - path: "*${{ matrix.ref }}.abi" - - abi-compare: - if: github.repository_owner == 'llvm' - runs-on: ubuntu-latest - needs: - - abi-dump-setup - - abi-dump - steps: - - name: Download baseline - uses: actions/download-artifact@v1 - with: - name: build-baseline - - name: Download latest - uses: actions/download-artifact@v1 - with: - name: build-latest - - - name: Install abi-compliance-checker - run: sudo apt-get install abi-compliance-checker - - name: Compare ABI - run: | - for lib in ${{ needs.abi-dump-setup.outputs.ABI_LIBS }}; do - abi-compliance-checker -lib $lib -old build-baseline/$lib*.abi -new build-latest/$lib*.abi - done - - name: Upload ABI Comparison - if: always() - uses: actions/upload-artifact@v2 - with: - name: compat-report-${{ github.sha }} - path: compat_reports/ - diff --git a/.github/workflows/libclc-tests.yml b/.github/workflows/libclc-tests.yml deleted file mode 100644 index f4d11e253501..000000000000 --- a/.github/workflows/libclc-tests.yml +++ /dev/null @@ -1,39 +0,0 @@ -name: libclc Tests - -on: - workflow_dispatch: - push: - ignore-forks: true - branches: - - 'release/**' - paths: - - 'libclc/**' - - '.github/workflows/libclc-tests.yml' - - '.github/workflows/llvm-project-tests.yml' - - '!clang/**' - - '!llvm/**' - pull_request: - ignore-forks: true - branches: - - 'release/**' - paths: - - 'libclc/**' - - '.github/workflows/libclc-tests.yml' - - '.github/workflows/llvm-project-tests.yml' - - '!clang/**' - - '!llvm/**' - -concurrency: - # Skip intermediate builds: always. - # Cancel intermediate builds: only if it is a pull request build. - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: ${{ startsWith(github.ref, 'refs/pull/') }} - -jobs: - check_libclc: - if: github.repository_owner == 'llvm' - name: Test libclc - uses: ./.github/workflows/llvm-project-tests.yml - with: - build_target: '' - projects: clang;libclc diff --git a/.github/workflows/lld-tests.yml b/.github/workflows/lld-tests.yml deleted file mode 100644 index b071affb6725..000000000000 --- a/.github/workflows/lld-tests.yml +++ /dev/null @@ -1,37 +0,0 @@ -name: LLD Tests - -on: - workflow_dispatch: - push: - ignore-forks: true - branches: - - 'release/**' - paths: - - 'lld/**' - - '.github/workflows/lld-tests.yml' - - '.github/workflows/llvm-project-tests.yml' - - '!llvm/**' - pull_request: - ignore-forks: true - branches: - - 'release/**' - paths: - - 'lld/**' - - '.github/workflows/lld-tests.yml' - - '.github/workflows/llvm-project-tests.yml' - - '!llvm/**' - -concurrency: - # Skip intermediate builds: always. - # Cancel intermediate builds: only if it is a pull request build. - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: ${{ startsWith(github.ref, 'refs/pull/') }} - -jobs: - check_lld: - if: github.repository_owner == 'llvm' - name: Test lld - uses: ./.github/workflows/llvm-project-tests.yml - with: - build_target: check-lld - projects: lld diff --git a/.github/workflows/lldb-tests.yml b/.github/workflows/lldb-tests.yml deleted file mode 100644 index 20a46437ae02..000000000000 --- a/.github/workflows/lldb-tests.yml +++ /dev/null @@ -1,40 +0,0 @@ -name: lldb Tests - -on: - workflow_dispatch: - push: - ignore-forks: true - branches: - - 'release/**' - paths: - - 'lldb/**' - - '.github/workflows/lldb-tests.yml' - - '.github/workflows/llvm-project-tests.yml' - - '!clang/**' - - '!llvm/**' - pull_request: - ignore-forks: true - branches: - - 'release/**' - paths: - - 'lldb/**' - - '.github/workflows/lldb-tests.yml' - - '.github/workflows/llvm-project-tests.yml' - - '!clang/**' - - '!llvm/**' - -concurrency: - # Skip intermediate builds: always. - # Cancel intermediate builds: only if it is a pull request build. - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: ${{ startsWith(github.ref, 'refs/pull/') }} - - -jobs: - build_lldb: - if: github.repository_owner == 'llvm' - name: Build lldb - uses: ./.github/workflows/llvm-project-tests.yml - with: - build_target: '' - projects: clang;lldb diff --git a/.github/workflows/llvm-project-tests.yml b/.github/workflows/llvm-project-tests.yml index a32fe80ae11c..070211ea322a 100644 --- a/.github/workflows/llvm-project-tests.yml +++ b/.github/workflows/llvm-project-tests.yml @@ -29,14 +29,14 @@ jobs: lit-tests: name: Lit Tests runs-on: ${{ matrix.os }} + env: + install_prefix: /usr/local strategy: fail-fast: false matrix: + target: [X86] os: - ubuntu-latest - # Use windows-2019 due to: - # https://developercommunity.visualstudio.com/t/Prev-Issue---with-__assume-isnan-/1597317 - - windows-2019 # We're using a specific version of macOS due to: # https://github.com/actions/virtual-environments/issues/5900 - macOS-11 @@ -73,23 +73,20 @@ jobs: # enough cache space for all the tests to run at once and still # fit under the 10 GB limit. max-size: 500M - key: sccache-${{ matrix.os }} - variant: sccache - - name: Build and Test - uses: llvm/actions/build-test-llvm-project@main + key: ${{ matrix.os }} + - name: Test clang macOS + if: ${{ matrix.os == 'macOS-11'}} env: # Workaround for https://github.com/actions/virtual-environments/issues/5900. # This should be a no-op for non-mac OSes PKG_CONFIG_PATH: /usr/local/Homebrew/Library/Homebrew/os/mac/pkgconfig//12 - with: - cmake_args: '-GNinja -DLLVM_ENABLE_PROJECTS="${{ inputs.projects }}" -DCMAKE_BUILD_TYPE=Release -DLLDB_INCLUDE_TESTS=OFF -DCMAKE_C_COMPILER_LAUNCHER=sccache -DCMAKE_CXX_COMPILER_LAUNCHER=sccache' - build_target: '${{ inputs.build_target }}' - - - name: Build and Test libclc - if: "!startsWith(matrix.os, 'windows') && contains(inputs.projects, 'libclc')" run: | - # Make sure all of LLVM libraries that llvm-config needs are built. - ninja -C build - cmake -G Ninja -S libclc -B libclc-build -DLLVM_CONFIG=`pwd`/build/bin/llvm-config -DLIBCLC_TARGETS_TO_BUILD="amdgcn--;amdgcn--amdhsa;r600--;nvptx--;nvptx64--;nvptx--nvidiacl;nvptx64--nvidiacl" - ninja -C libclc-build - ninja -C libclc-build test + ./build-llvm-project.sh -t X86 -e "clang" -p /usr/local -s -n $(sysctl -n hw.logicalcpu) -i -v + cd build + make check-all + - name: Test clang ubuntu + if: ${{ matrix.os == 'ubuntu-latest'}} + run: | + ./build-llvm-project.sh -t X86 -e "${{ inputs.projects }}" -p /usr/local -s -n $(nproc) -i -v + cd build + make check-all diff --git a/.github/workflows/llvm-tests.yml b/.github/workflows/llvm-tests.yml index 83091da4bbb4..7264c62ce134 100644 --- a/.github/workflows/llvm-tests.yml +++ b/.github/workflows/llvm-tests.yml @@ -28,168 +28,9 @@ concurrency: jobs: check_all: - if: github.repository_owner == 'llvm' - name: Test llvm,clang,libclc + if: github.repository_owner == 'flang-compiler' + name: Test llvm,clang uses: ./.github/workflows/llvm-project-tests.yml with: build_target: check-all - projects: clang;libclc - - # These need to be separate from the check_all job, becuase there is not enough disk - # space to build all these projects on Windows. - build_lldb: - if: github.repository_owner == 'llvm' - name: Build lldb - uses: ./.github/workflows/llvm-project-tests.yml - with: - build_target: '' - projects: clang;lldb - - check_lld: - if: github.repository_owner == 'llvm' - name: Test lld - uses: ./.github/workflows/llvm-project-tests.yml - with: - build_target: check-lld - projects: lld - - abi-dump-setup: - if: github.repository_owner == 'llvm' - runs-on: ubuntu-latest - outputs: - BASELINE_REF: ${{ steps.vars.outputs.BASELINE_REF }} - ABI_HEADERS: ${{ steps.vars.outputs.ABI_HEADERS }} - BASELINE_VERSION_MAJOR: ${{ steps.vars.outputs.BASELINE_VERSION_MAJOR }} - LLVM_VERSION_MAJOR: ${{ steps.version.outputs.LLVM_VERSION_MAJOR }} - LLVM_VERSION_MINOR: ${{ steps.version.outputs.LLVM_VERSION_MINOR }} - LLVM_VERSION_PATCH: ${{ steps.version.outputs.LLVM_VERSION_PATCH }} - steps: - - name: Checkout source - uses: actions/checkout@v3 - with: - fetch-depth: 250 - - - name: Get LLVM version - id: version - uses: llvm/actions/get-llvm-version@main - - - name: Setup Variables - id: vars - run: | - if [ ${{ steps.version.outputs.LLVM_VERSION_MINOR }} -ne 0 -o ${{ steps.version.outputs.LLVM_VERSION_PATCH }} -eq 0 ]; then - echo ::set-output name=BASELINE_VERSION_MAJOR::$(( ${{ steps.version.outputs.LLVM_VERSION_MAJOR }} - 1)) - echo ::set-output name=ABI_HEADERS::llvm-c - else - echo ::set-output name=BASELINE_VERSION_MAJOR::${{ steps.version.outputs.LLVM_VERSION_MAJOR }} - echo ::set-output name=ABI_HEADERS::. - fi - - abi-dump: - if: github.repository_owner == 'llvm' - needs: abi-dump-setup - runs-on: ubuntu-latest - strategy: - matrix: - name: - - build-baseline - - build-latest - include: - - name: build-baseline - llvm_version_major: ${{ needs.abi-dump-setup.outputs.BASELINE_VERSION_MAJOR }} - ref: llvmorg-${{ needs.abi-dump-setup.outputs.BASELINE_VERSION_MAJOR }}.0.0 - repo: llvm/llvm-project - - name: build-latest - llvm_version_major: ${{ needs.abi-dump-setup.outputs.LLVM_VERSION_MAJOR }} - ref: ${{ github.sha }} - repo: ${{ github.repository }} - steps: - - name: Install Ninja - uses: llvm/actions/install-ninja@main - - name: Install abi-compliance-checker - run: | - sudo apt-get install abi-dumper autoconf pkg-config - - name: Install universal-ctags - run: | - git clone https://github.com/universal-ctags/ctags.git - cd ctags - ./autogen.sh - ./configure - sudo make install - - name: Download source code - uses: llvm/actions/get-llvm-project-src@main - with: - ref: ${{ matrix.ref }} - repo: ${{ matrix.repo }} - - name: Configure - run: | - mkdir install - cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=Debug -DLLVM_TARGETS_TO_BUILD="" -DLLVM_BUILD_LLVM_DYLIB=ON -DCMAKE_C_FLAGS_DEBUG="-g1 -Og" -DCMAKE_CXX_FLAGS_DEBUG="-g1 -Og" -DCMAKE_INSTALL_PREFIX=`pwd`/install llvm - - name: Build - # Need to run install-LLVM twice to ensure the symlink is installed (this is a bug). - run: | - ninja -C build install-LLVM - ninja -C build install-LLVM - ninja -C build install-llvm-headers - - name: Dump ABI - run: | - if [ "${{ needs.abi-dump-setup.outputs.ABI_HEADERS }}" = "llvm-c" ]; then - nm ./install/lib/libLLVM.so | awk "/T _LLVM/ || /T LLVM/ { print $3 }" | sort -u | sed -e "s/^_//g" | cut -d ' ' -f 3 > llvm.symbols - # Even though the -symbols-list option doesn't seem to filter out the symbols, I believe it speeds up processing, so I'm leaving it in. - export EXTRA_ARGS="-symbols-list llvm.symbols" - else - touch llvm.symbols - fi - abi-dumper $EXTRA_ARGS -lver ${{ matrix.ref }} -skip-cxx -public-headers ./install/include/${{ needs.abi-dump-setup.outputs.ABI_HEADERS }} -o ${{ matrix.ref }}.abi ./install/lib/libLLVM.so - # Remove symbol versioning from dumps, so we can compare across major versions. - sed -i 's/LLVM_${{ matrix.llvm_version_major }}/LLVM_NOVERSION/' ${{ matrix.ref }}.abi - - name: Upload ABI file - uses: actions/upload-artifact@v1 - with: - name: ${{ matrix.name }} - path: ${{ matrix.ref }}.abi - - - name: Upload symbol list file - if: matrix.name == 'build-baseline' - uses: actions/upload-artifact@v1 - with: - name: symbol-list - path: llvm.symbols - - abi-compare: - if: github.repository_owner == 'llvm' - runs-on: ubuntu-latest - needs: - - abi-dump-setup - - abi-dump - steps: - - name: Download baseline - uses: actions/download-artifact@v1 - with: - name: build-baseline - - name: Download latest - uses: actions/download-artifact@v1 - with: - name: build-latest - - name: Download symbol list - uses: actions/download-artifact@v1 - with: - name: symbol-list - - - name: Install abi-compliance-checker - run: sudo apt-get install abi-compliance-checker - - name: Compare ABI - run: | - if [ -s symbol-list/llvm.symbols ]; then - # This option doesn't seem to work with the ABI dumper, so passing it here. - export EXTRA_ARGS="-symbols-list symbol-list/llvm.symbols" - fi - # FIXME: Reading of gzip'd abi files on the GitHub runners stop - # working some time in March of 2021, likely due to a change in the - # runner's environment. - abi-compliance-checker $EXTRA_ARGS -l libLLVM.so -old build-baseline/*.abi -new build-latest/*.abi || test "${{ needs.abi-dump-setup.outputs.ABI_HEADERS }}" = "llvm-c" - - name: Upload ABI Comparison - if: always() - uses: actions/upload-artifact@v1 - with: - name: compat-report-${{ github.sha }} - path: compat_reports/ + projects: clang;openmp diff --git a/.github/workflows/pre-compile_llvm.yml b/.github/workflows/pre-compile_llvm.yml new file mode 100644 index 000000000000..7cb4b8ed72bd --- /dev/null +++ b/.github/workflows/pre-compile_llvm.yml @@ -0,0 +1,80 @@ +name: Pre-compile llvm + +on: + workflow_dispatch: + push: + branches: [ release_11x, release_12x, release_13x, release_14x ] + +jobs: + build: + runs-on: ubuntu-20.04 + strategy: + matrix: + target: [X86] + cc: [clang, gcc] + version: [10, 11] + + steps: + - if: matrix.cc == 'clang' + run: | + echo "cpp=clang++" >> $GITHUB_ENV + sudo add-apt-repository ppa:ubuntu-toolchain-r/ppa + sudo touch /etc/apt/sources.list.d/llvm.list + echo 'deb http://apt.llvm.org/focal/ llvm-toolchain-focal-11 main' | sudo tee -a /etc/apt/sources.list.d/llvm.list + echo 'deb-src http://apt.llvm.org/focal/ llvm-toolchain-focal-11 main' | sudo tee -a /etc/apt/sources.list.d/llvm.list + wget -q -O - http://apt.llvm.org/llvm-snapshot.gpg.key|sudo apt-key add - + sudo apt update + sudo apt install -f -y llvm-${{ matrix.version }} clang-${{ matrix.version}} + + - if: matrix.cc == 'gcc' && matrix.version == '10' + run: | + echo "cpp=g++" >> $GITHUB_ENV + sudo add-apt-repository ppa:ubuntu-toolchain-r/ppa + sudo apt install gcc-10 g++-10 + + - if: matrix.cc == 'gcc' && matrix.version == '11' + run: | + echo "cpp=g++" >> $GITHUB_ENV + sudo add-apt-repository ppa:ubuntu-toolchain-r/ppa + sudo apt install gcc-11 g++-11 + + - name: Check tools + run: | + git --version + cmake --version + make --version + ${{ matrix.cc }}-${{ matrix.version }} --version + ${{env.cpp}}-${{ matrix.version }} --version + + - name: Extract branch name + run: echo "::set-output name=branch::${GITHUB_REF#refs/heads/}" + id: extract_branch + + - name: Build llvm + run: | + # exit the llvm dir, so the path is the same on subsequent projects + cd ../.. + rm -rf classic-flang-llvm-project + # clone manually, because checkout does not allow exiting llvm dir + git clone --depth 1 --single-branch --branch ${{ steps.extract_branch.outputs.branch }} https://github.com/flang-compiler/classic-flang-llvm-project.git + cd classic-flang-llvm-project + # After build place the artifacts in classic-flang-llvm-project/classic-flang-llvm-project, so Upload can find them. + mkdir classic-flang-llvm-project + ./build-llvm-project.sh \ + -t ${{ matrix.target }} \ + -p /usr/local \ + -a /usr/bin/${{ matrix.cc }}-${{ matrix.version }} \ + -b /usr/bin/${{env.cpp}}-${{ matrix.version }} \ + -n $(nproc) \ + -v + # Archive the source + build directories for future installation + cd .. + tar -zcf llvm_build.tar.gz classic-flang-llvm-project + # Upload will only look in $GITHUB_WORKSPACE or its subdirs. + mv llvm_build.tar.gz classic-flang-llvm-project/classic-flang-llvm-project/. + + - name: Upload llvm + uses: actions/upload-artifact@v2 + with: + name: llvm_build_${{ matrix.target }}_${{ matrix.cc }}_${{ matrix.version }}_${{ steps.extract_branch.outputs.branch }} + path: llvm_build.tar.gz diff --git a/.github/workflows/repo-lockdown.yml b/.github/workflows/repo-lockdown.yml deleted file mode 100644 index f7b56907cbaf..000000000000 --- a/.github/workflows/repo-lockdown.yml +++ /dev/null @@ -1,19 +0,0 @@ -name: 'Repo Lockdown' -on: - pull_request_target: - types: opened - -permissions: - pull-requests: write - -jobs: - action: - runs-on: ubuntu-latest - if: github.repository == 'llvm/llvm-project' - steps: - - uses: dessant/repo-lockdown@v2 - with: - process-only: 'prs' - pr-comment: > - This repository does not accept pull requests. - Please follow http://llvm.org/docs/Contributing.html#how-to-submit-a-patch for contribution to LLVM. diff --git a/build-llvm-project.sh b/build-llvm-project.sh new file mode 100755 index 000000000000..5e3368637d99 --- /dev/null +++ b/build-llvm-project.sh @@ -0,0 +1,94 @@ +#!/bin/bash + +# Initialize our own variables: +TARGET="X86" +BUILD_TYPE="Release" +INSTALL_PREFIX="/usr/local" +NPROC=1 +USE_CCACHE="0" +DO_INSTALL="0" +USE_SUDO="0" +C_COMPILER_PATH="/usr/bin/gcc" +CXX_COMPILER_PATH="/usr/bin/g++" +LLVM_ENABLE_PROJECTS="clang;openmp" +VERBOSE="" + +set -e # Exit script on first error. + +function print_usage { + echo "Usage: ./build-llvm-project.sh [options]"; + echo ""; + echo "Build and install classic-flang-llvm-project."; + echo "Run this script in a directory with project sources."; + echo "Example:"; + echo " $ git clone https://github.com/flang-compiler/classic-flang-llvm-project"; + echo " $ cd classic-flang-llvm-project"; + echo " $ .github/workflows/build-llvm-project.sh -t X86 -p /install/prefix/ \\"; + echo " $ -a /usr/bin/gcc-10 -b /usr/bin/g++-10 -i -s"; + echo ""; + echo "Options:"; + echo " -t Target to build for (X86, AArch64, PowerPC). Default: X86"; + echo " -d Set the CMake build type. Default: Release"; + echo " -p Install prefix. Default: /usr/local"; + echo " -n Number of parallel jobs. Default: 1"; + echo " -c Use ccache. Default: 0 - do not use ccache"; + echo " -i Install the build. Default 0 - just build, do not install"; + echo " -s Use sudo to install. Default: 0 - do not use sudo"; + echo " -a C compiler path. Default: /usr/bin/gcc"; + echo " -b C++ compiler path. Default: /usr/bin/g++"; + echo " -e List of the LLVM sub-projects to build. Default: clang;openmp"; + echo " -v Enable verbose output"; +} +while getopts "t:d:p:n:c?i?s?a:b:e:v" opt; do + case "$opt" in + t) TARGET=$OPTARG;; + d) BUILD_TYPE=$OPTARG;; + p) INSTALL_PREFIX=$OPTARG;; + n) NPROC=$OPTARG;; + c) USE_CCACHE="1";; + i) DO_INSTALL="1";; + s) USE_SUDO="1";; + a) C_COMPILER_PATH=$OPTARG;; + b) CXX_COMPILER_PATH=$OPTARG;; + e) LLVM_ENABLE_PROJECTS=$OPTARG;; + v) VERBOSE="1";; + ?) print_usage; exit 0;; + esac +done + +CMAKE_OPTIONS="-DCMAKE_INSTALL_PREFIX=$INSTALL_PREFIX \ + -DCMAKE_BUILD_TYPE=$BUILD_TYPE \ + -DCMAKE_C_COMPILER=$C_COMPILER_PATH \ + -DCMAKE_CXX_COMPILER=$CXX_COMPILER_PATH \ + -DLLVM_TARGETS_TO_BUILD=$TARGET \ + -DLLVM_ENABLE_CLASSIC_FLANG=ON \ + -DFLANG_BUILD_NEW_DRIVER=OFF" +# Warning: the -DLLVM_ENABLE_PROJECTS option is specified with cmake +# to avoid issues with nested quotation marks + +if [ $USE_CCACHE == "1" ]; then + echo "Build using ccache" + CMAKE_OPTIONS="$CMAKE_OPTIONS \ + -DCMAKE_C_COMPILER_LAUNCHER=ccache \ + -DCMAKE_CXX_COMPILER_LAUNCHER=ccache" +fi + +# Build and install +mkdir -p build && cd build +if [ -n "$VERBOSE" ]; then + set -x +fi +cmake $CMAKE_OPTIONS -DLLVM_ENABLE_PROJECTS=$LLVM_ENABLE_PROJECTS ../llvm +set +x +make -j$NPROC VERBOSE=$VERBOSE +if [ $DO_INSTALL == "1" ]; then + if [ $USE_SUDO == "1" ]; then + echo "Install with sudo" + sudo make install + else + echo "Install without sudo" + make install + fi +fi +cd .. + diff --git a/clang/test/Driver/flang/classic-flang-must-preprocess.F b/clang/test/Driver/flang/classic-flang-must-preprocess.F index d52c1cf8d3c0..cf2e4207a4a0 100644 --- a/clang/test/Driver/flang/classic-flang-must-preprocess.F +++ b/clang/test/Driver/flang/classic-flang-must-preprocess.F @@ -5,8 +5,8 @@ ! RUN: %clang --driver-mode=flang -target x86_64-unknown-linux-gnu -c %s -### 2>&1 \ ! RUN: | FileCheck %s -! CHECK: "flang1" +! CHECK: "{{.*}}flang1" ! CHECK-SAME: "-preprocess" ! CHECK-SAME: "-nofreeform" -! CHECK-NEXT: "flang2" +! CHECK-NEXT: "{{.*}}flang2" ! CHECK-NEXT: {{clang.* "-cc1"}} diff --git a/clang/test/Driver/flang/classic-flang-must-preprocess.F95 b/clang/test/Driver/flang/classic-flang-must-preprocess.F95 index 7d452a535784..85ec49fe3fab 100644 --- a/clang/test/Driver/flang/classic-flang-must-preprocess.F95 +++ b/clang/test/Driver/flang/classic-flang-must-preprocess.F95 @@ -5,8 +5,8 @@ ! RUN: %clang --driver-mode=flang -target x86_64-unknown-linux-gnu -c %s -### 2>&1 \ ! RUN: | FileCheck %s -! CHECK: "flang1" +! CHECK: "{{.*}}flang1" ! CHECK-SAME: "-preprocess" ! CHECK-SAME: "-freeform" -! CHECK-NEXT: "flang2" +! CHECK-NEXT: "{{.*}}flang2" ! CHECK-NEXT: {{clang.* "-cc1"}} diff --git a/clang/test/Driver/flang/classic-flang.f b/clang/test/Driver/flang/classic-flang.f index 98f74d9626d7..c680abc076ae 100644 --- a/clang/test/Driver/flang/classic-flang.f +++ b/clang/test/Driver/flang/classic-flang.f @@ -5,10 +5,10 @@ ! RUN: %clang --driver-mode=flang -target x86_64-unknown-linux-gnu -c %s -### 2>&1 \ ! RUN: | FileCheck %s -! CHECK: "flang1" +! CHECK: "{{.*}}flang1" ! CHECK-NOT: "-preprocess" ! CHECK-SAME: "-nofreeform" -! CHECK-NEXT: "flang2" +! CHECK-NEXT: "{{.*}}flang2" ! CHECK-NEXT: {{clang.* "-cc1"}} ! Check that the driver invokes flang1 correctly when preprocessing is @@ -16,11 +16,11 @@ ! RUN: %clang --driver-mode=flang -target x86_64-unknown-linux-gnu -E %s -### 2>&1 \ ! RUN: | FileCheck --check-prefix=CHECK-PREPROCESS %s -! CHECK-PREPROCESS: "flang1" +! CHECK-PREPROCESS: "{{.*}}flang1" ! CHECK-PREPROCESS-SAME: "-preprocess" ! CHECK-PREPROCESS-SAME: "-es" ! CHECK-PREPROCESS-SAME: "-pp" -! CHECK-PREPROCESS-NOT: "flang1" -! CHECK-PREPROCESS-NOT: "flang2" +! CHECK-PREPROCESS-NOT: "{{.*}}flang1" +! CHECK-PREPROCESS-NOT: "{{.*}}flang2" ! CHECK-PREPROCESS-NOT: {{clang.* "-cc1"}} ! CHECK-PREPROCESS-NOT: {{clang.* "-cc1as"}} diff --git a/clang/test/Driver/flang/classic-flang.f95 b/clang/test/Driver/flang/classic-flang.f95 index 0b92c799392a..6fce9c61713c 100644 --- a/clang/test/Driver/flang/classic-flang.f95 +++ b/clang/test/Driver/flang/classic-flang.f95 @@ -5,10 +5,10 @@ ! RUN: %clang --driver-mode=flang -target x86_64-unknown-linux-gnu -c %s -### 2>&1 \ ! RUN: | FileCheck --check-prefix=CHECK-OBJECT %s -! CHECK-OBJECT: "flang1" +! CHECK-OBJECT: "{{.*}}flang1" ! CHECK-OBJECT-NOT: "-preprocess" ! CHECK-OBJECT-SAME: "-freeform" -! CHECK-OBJECT-NEXT: "flang2" +! CHECK-OBJECT-NEXT: "{{.*}}flang2" ! CHECK-OBJECT-SAME: "-asm" [[LLFILE:.*.ll]] ! CHECK-OBJECT-NEXT: {{clang.* "-cc1"}} ! CHECK-OBJECT-SAME: "-o" "classic-flang.o" @@ -20,12 +20,12 @@ ! RUN: %clang --driver-mode=flang -target x86_64-unknown-linux-gnu -E %s -### 2>&1 \ ! RUN: | FileCheck --check-prefix=CHECK-PREPROCESS %s -! CHECK-PREPROCESS: "flang1" +! CHECK-PREPROCESS: "{{.*}}flang1" ! CHECK-PREPROCESS-SAME: "-preprocess" ! CHECK-PREPROCESS-SAME: "-es" ! CHECK-PREPROCESS-SAME: "-pp" -! CHECK-PREPROCESS-NOT: "flang1" -! CHECK-PREPROCESS-NOT: "flang2" +! CHECK-PREPROCESS-NOT: "{{.*}}flang1" +! CHECK-PREPROCESS-NOT: "{{.*}}flang2" ! CHECK-PREPROCESS-NOT: {{clang.* "-cc1"}} ! CHECK-PREPROCESS-NOT: {{clang.* "-cc1as"}} @@ -34,8 +34,8 @@ ! RUN: %clang --driver-mode=flang -target x86_64-unknown-linux-gnu -integrated-as -S %s -### 2>&1 \ ! RUN: | FileCheck --check-prefix=CHECK-ASM %s -! CHECK-ASM: "flang1" -! CHECK-ASM-NEXT: "flang2" +! CHECK-ASM: "{{.*}}flang1" +! CHECK-ASM-NEXT: "{{.*}}flang2" ! CHECK-ASM-SAME: "-asm" [[LLFILE:.*.ll]] ! CHECK-ASM-NEXT: {{clang.* "-cc1"}} ! CHECK-ASM-SAME: "-o" "classic-flang.s" -- Gitee From b2868ce0d84675118014e767eb48fcfa034ecc32 Mon Sep 17 00:00:00 2001 From: Sourabh Singh Tomar Date: Fri, 16 Apr 2021 12:29:12 +0530 Subject: [PATCH 08/33] [DebugInfo] Support of `-gpubnames` in Driver --- clang/lib/Driver/ToolChains/ClassicFlang.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/clang/lib/Driver/ToolChains/ClassicFlang.cpp b/clang/lib/Driver/ToolChains/ClassicFlang.cpp index f297989910c5..162970e13832 100644 --- a/clang/lib/Driver/ToolChains/ClassicFlang.cpp +++ b/clang/lib/Driver/ToolChains/ClassicFlang.cpp @@ -355,6 +355,13 @@ void ClassicFlang::ConstructJob(Compilation &C, const JobAction &JA, CommonCmdArgs.push_back("0x1000000"); else if (GDwarfArg->getOption().matches(options::OPT_gdwarf_5)) // -gdwarf-5 CommonCmdArgs.push_back("0x2000000"); + // Handle `-gpubnames` option separately. + for (auto Arg : Args.filtered(options::OPT_gpubnames)) { + Arg->claim(); + CommonCmdArgs.push_back("-x"); + CommonCmdArgs.push_back("120"); + CommonCmdArgs.push_back("0x40000000"); // -gpubnames + } } // -Mipa has no effect -- Gitee From c1c7b44bb10bda9c351a939040d0a4d93249157a Mon Sep 17 00:00:00 2001 From: Isuru Fernando Date: Fri, 6 Aug 2021 05:10:31 -0700 Subject: [PATCH 09/33] [Driver] Support macOS --- clang/lib/Driver/ToolChain.cpp | 4 +++- clang/lib/Driver/ToolChains/Darwin.cpp | 12 ++++++++++++ clang/lib/Driver/ToolChains/Gnu.cpp | 2 +- 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp index 4dd7263bb30b..86b778cce97a 100644 --- a/clang/lib/Driver/ToolChain.cpp +++ b/clang/lib/Driver/ToolChain.cpp @@ -1074,7 +1074,9 @@ void ToolChain::AddFortranStdlibLibArgs(const ArgList &Args, CmdArgs.push_back("-Bdynamic"); CmdArgs.push_back("-lm"); - CmdArgs.push_back("-lrt"); + + if (!Triple.isOSDarwin()) + CmdArgs.push_back("-lrt"); // Allways link Fortran executables with Pthreads CmdArgs.push_back("-lpthread"); diff --git a/clang/lib/Driver/ToolChains/Darwin.cpp b/clang/lib/Driver/ToolChains/Darwin.cpp index bada811daadf..13ec8894c021 100644 --- a/clang/lib/Driver/ToolChains/Darwin.cpp +++ b/clang/lib/Driver/ToolChains/Darwin.cpp @@ -678,6 +678,18 @@ void darwin::Linker::ConstructJob(Compilation &C, const JobAction &JA, if (getToolChain().ShouldLinkCXXStdlib(Args)) getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs); +#ifdef ENABLE_CLASSIC_FLANG + // Add Fortran runtime libraries + if (needFortranLibs(getToolChain().getDriver(), Args)) { + getToolChain().AddFortranStdlibLibArgs(Args, CmdArgs); + } else { + // Claim "no Flang libraries" arguments if any + for (auto Arg : Args.filtered(options::OPT_noFlangLibs)) { + Arg->claim(); + } + } +#endif + bool NoStdOrDefaultLibs = Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs); bool ForceLinkBuiltins = Args.hasArg(options::OPT_fapple_link_rtlib); diff --git a/clang/lib/Driver/ToolChains/Gnu.cpp b/clang/lib/Driver/ToolChains/Gnu.cpp index 9d5707713210..69e34dfa3fed 100644 --- a/clang/lib/Driver/ToolChains/Gnu.cpp +++ b/clang/lib/Driver/ToolChains/Gnu.cpp @@ -572,7 +572,7 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA, if (needFortranLibs(D, Args)) { ToolChain.AddFortranStdlibLibArgs(Args, CmdArgs); } else { - // Claim "no Flang libraries" arguments if any + // Claim "no Flang libraries" arguments if any for (auto Arg : Args.filtered(options::OPT_noFlangLibs)) { Arg->claim(); } -- Gitee From b2f3b1077fb69e6de84abbd1576c1f867f996a9d Mon Sep 17 00:00:00 2001 From: Itay Bookstein Date: Wed, 22 Sep 2021 16:56:52 +0300 Subject: [PATCH 10/33] [DebugInfo]: Remove dangerous dead function (-Wreturn-stack-address) Signed-off-by: Itay Bookstein --- llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h | 8 -------- llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp | 6 ------ 2 files changed, 14 deletions(-) diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h index 2e41e1e06272..61412cde34c8 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h @@ -146,14 +146,6 @@ public: std::vector ExprRefedBaseTypes; -private: - DenseMap> *globalVarMap; -public: - void setGlobalVarMap( - DenseMap> *p = nullptr) { - globalVarMap = p; - } - /// Get or create global variable DIE. DIE * getOrCreateGlobalVariableDIE(const DIGlobalVariable *GV, diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp index 18087d607148..c8cbbf6eb464 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -1215,17 +1215,11 @@ void DwarfDebug::beginModule(Module *M) { } DenseSet Processed; -#if 0 - CU.setGlobalVarMap(&GVMap); -#endif for (auto *GVE : CUNode->getGlobalVariables()) { DIGlobalVariable *GV = GVE->getVariable(); if (Processed.insert(GV).second) CU.getOrCreateGlobalVariableDIE(GV, sortGlobalExprs(GVMap[GV])); } -#if 0 - CU.setGlobalVarMap(); -#endif for (auto *Ty : CUNode->getEnumTypes()) CU.getOrCreateTypeDIE(cast(Ty)); -- Gitee From 4278032246410c8c446f04d66dc41420493d016d Mon Sep 17 00:00:00 2001 From: Itay Bookstein Date: Wed, 22 Sep 2021 17:12:19 +0300 Subject: [PATCH 11/33] [ClassicFlang][Driver] Fix warnings * -Wsuggest-override for ClassicFlangMacroBuilder::defineMacro * -Wrange-loop-construct when iterating over llvm::opt::Arg::getValues Signed-off-by: Itay Bookstein --- clang/lib/Driver/ToolChains/Clang.cpp | 4 ++-- clang/lib/Driver/ToolChains/ClassicFlang.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index a8fd2ae6bfcb..69aa3404f58c 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -5109,7 +5109,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, PassRemarkVal = ".*"; Args.ClaimAllArgs(options::OPT_Minfoall); } else if (Arg *A = Args.getLastArg(options::OPT_Minfo_EQ)) { - for (const StringRef &val : A->getValues()) { + for (StringRef val : A->getValues()) { if (val.equals("all")) { PassRemarkVal = ".*"; break; @@ -5135,7 +5135,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, PassRemarkVal = ".*"; Args.ClaimAllArgs(options::OPT_Mneginfoall); } else if (Arg *A = Args.getLastArg(options::OPT_Mneginfo_EQ)) { - for (const StringRef &val : A->getValues()) { + for (StringRef val : A->getValues()) { if (val.equals("all")) { PassRemarkVal = ".*"; break; diff --git a/clang/lib/Driver/ToolChains/ClassicFlang.cpp b/clang/lib/Driver/ToolChains/ClassicFlang.cpp index 162970e13832..3bfbc410ffbf 100644 --- a/clang/lib/Driver/ToolChains/ClassicFlang.cpp +++ b/clang/lib/Driver/ToolChains/ClassicFlang.cpp @@ -50,7 +50,7 @@ class ClassicFlangMacroBuilder : public MacroBuilder { ClassicFlangMacroBuilder(ArgStringList &UpperCmdArgs, const ArgList &DriverArgs, llvm::raw_string_ostream &Output) : MacroBuilder(Output), CmdArgs(UpperCmdArgs), DriverArgs(DriverArgs) { } - virtual void defineMacro(const Twine &Name, const Twine &Value = "1") { + virtual void defineMacro(const Twine &Name, const Twine &Value = "1") override { CmdArgs.push_back("-def"); CmdArgs.push_back(DriverArgs.MakeArgString(Name + Twine('=') + Value)); } @@ -212,7 +212,7 @@ void ClassicFlang::ConstructJob(Compilation &C, const JobAction &JA, // Contiguous pointer checks if (Arg *A = Args.getLastArg(options::OPT_fsanitize_EQ)) { - for (const StringRef &val : A->getValues()) { + for (StringRef val : A->getValues()) { if (val.equals("discontiguous") || val.equals("undefined") ) { // -x 54 0x40 -x 54 0x80 -x 54 0x200 UpperCmdArgs.push_back("-x"); -- Gitee From ec2f7430bf6066eeb0ddca1fff5c10596769709d Mon Sep 17 00:00:00 2001 From: Richard Barton Date: Wed, 26 Jan 2022 17:30:32 +0000 Subject: [PATCH 12/33] [driver] Add -emit-flang-llvm option -emit-flang-llvm instructs flang to stop after flang2 and dump the LLVM IR. Can be useful for debugging and also would be a useful option for testing flang output more accurately. Signed-off-by: Richard Barton --- clang/include/clang/Driver/Options.td | 4 ++++ clang/lib/Driver/Driver.cpp | 3 +++ clang/lib/Driver/ToolChains/ClassicFlang.cpp | 7 +++++++ 3 files changed, 14 insertions(+) diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 09508e82f4bb..e462b49ee683 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -1103,6 +1103,10 @@ def d_Flag : Flag<["-"], "d">, Group; def d_Joined : Joined<["-"], "d">, Group; def emit_ast : Flag<["-"], "emit-ast">, Flags<[CoreOption]>, HelpText<"Emit Clang AST files for source inputs">; +#ifdef ENABLE_CLASSIC_FLANG +def emit_flang_llvm : Flag<["-"], "emit-flang-llvm">, + HelpText<"Emit Flang LLVM files for source inputs">; +#endif def emit_llvm : Flag<["-"], "emit-llvm">, Flags<[CC1Option, FC1Option, FlangOption]>, Group, HelpText<"Use the LLVM representation for assembler and object files">; def emit_interface_stubs : Flag<["-"], "emit-interface-stubs">, Flags<[CC1Option]>, Group, diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp index 8fc5d09437f6..386919d1c436 100644 --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -359,6 +359,9 @@ phases::ID Driver::getFinalPhase(const DerivedArgList &DAL, } else if ((PhaseArg = DAL.getLastArg(options::OPT_fsyntax_only)) || (PhaseArg = DAL.getLastArg(options::OPT_print_supported_cpus)) || (PhaseArg = DAL.getLastArg(options::OPT_module_file_info)) || +#ifdef ENABLE_CLASSIC_FLANG + (PhaseArg = DAL.getLastArg(options::OPT_emit_flang_llvm)) || +#endif (PhaseArg = DAL.getLastArg(options::OPT_verify_pch)) || (PhaseArg = DAL.getLastArg(options::OPT_rewrite_objc)) || (PhaseArg = DAL.getLastArg(options::OPT_rewrite_legacy_objc)) || diff --git a/clang/lib/Driver/ToolChains/ClassicFlang.cpp b/clang/lib/Driver/ToolChains/ClassicFlang.cpp index 3bfbc410ffbf..9c974a4df585 100644 --- a/clang/lib/Driver/ToolChains/ClassicFlang.cpp +++ b/clang/lib/Driver/ToolChains/ClassicFlang.cpp @@ -86,6 +86,13 @@ void ClassicFlang::ConstructJob(Compilation &C, const JobAction &JA, llvm::sys::path::replace_extension(Stem, ""); } +#ifdef ENABLE_CLASSIC_FLANG + if (Args.hasArg(options::OPT_emit_flang_llvm)) { + // -emit-flang-llvm only supports asm output so claim -S to prevent warning + Args.ClaimAllArgs(options::OPT_S); + } +#endif + // Add input file name to the compilation line UpperCmdArgs.push_back(Input.getBaseInput()); -- Gitee From b68850dea5e5515f4b0518b6aded46c6ea4bd48b Mon Sep 17 00:00:00 2001 From: Richard Barton Date: Tue, 1 Feb 2022 08:21:08 +0000 Subject: [PATCH 13/33] [driver] Add regression test --- .../Driver/flang/classic-flang-emit-flang-llvm.f95 | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 clang/test/Driver/flang/classic-flang-emit-flang-llvm.f95 diff --git a/clang/test/Driver/flang/classic-flang-emit-flang-llvm.f95 b/clang/test/Driver/flang/classic-flang-emit-flang-llvm.f95 new file mode 100644 index 000000000000..225207c85db7 --- /dev/null +++ b/clang/test/Driver/flang/classic-flang-emit-flang-llvm.f95 @@ -0,0 +1,10 @@ +! REQUIRES: classic_flang + +! Check that the -emit-flang-llvm option dumps LLVM IR pre-optimisation + +! RUN: %clang --driver-mode=flang -emit-flang-llvm -S -o %t.ll %s -### 2>&1 \ +! RUN: | FileCheck %s +! CHECK-NOT: argument unused during compilation: '-S' +! CHECK: "{{.*}}flang1" +! CHECK-NEXT: "{{.*}}flang2" +! CHECK-NOT: "{{.*}}clang{{.*}}" "-cc1" -- Gitee From 250df95305737f5c549b2585ab5723e9fffd0531 Mon Sep 17 00:00:00 2001 From: Richard Barton Date: Mon, 15 Nov 2021 09:47:24 +0000 Subject: [PATCH 14/33] [driver] Add infrastructure for testing the flang-driver in lit Add %flang as a tool substitution available in lit tests. This apes the way %clang is defined and adds a $FLANG override in a similar vein. To avoid this being dead code, add a single test to check the flang driver is reporting the correct phases when running under various phase control options. Signed-off-by: Richard Barton --- clang/test/Driver/fortran-phases.f90 | 102 +++++++++++++++++++++++++++ llvm/utils/lit/lit/TestingConfig.py | 1 + llvm/utils/lit/lit/llvm/config.py | 10 +++ 3 files changed, 113 insertions(+) create mode 100644 clang/test/Driver/fortran-phases.f90 diff --git a/clang/test/Driver/fortran-phases.f90 b/clang/test/Driver/fortran-phases.f90 new file mode 100644 index 000000000000..5a79bb26bcde --- /dev/null +++ b/clang/test/Driver/fortran-phases.f90 @@ -0,0 +1,102 @@ +! Test to see that the correct phases are run for the commandline input + +! REQUIRES: classic_flang + +! RUN: %flang -ccc-print-phases 2>&1 %s | FileCheck %s --check-prefix=LINK-NOPP +! RUN: %flang -ccc-print-phases -c 2>&1 %s | FileCheck %s --check-prefix=CONLY-NOPP +! RUN: %flang -ccc-print-phases -S 2>&1 %s | FileCheck %s --check-prefix=AONLY-NOPP +! RUN: %flang -ccc-print-phases -c -emit-llvm 2>&1 %s | FileCheck %s --check-prefix=LLONLY-NOPP +! RUN: %flang -ccc-print-phases -S -emit-llvm 2>&1 %s | FileCheck %s --check-prefix=LLONLY-NOPP +! RUN: %flang -ccc-print-phases -fsyntax-only 2>&1 %s | FileCheck %s --check-prefix=SONLY-NOPP +! RUN: %flang -ccc-print-phases -E 2>&1 %s | FileCheck %s --check-prefix=PPONLY-NOPP + +! RUN: %flang -ccc-print-phases 2>&1 -x f95-cpp-input %s | FileCheck %s --check-prefix=LINK +! RUN: %flang -ccc-print-phases 2>&1 -x f95-cpp-input %s | FileCheck %s --check-prefix=LINK +! RUN: %flang -ccc-print-phases -c 2>&1 -x f95-cpp-input %s | FileCheck %s --check-prefix=CONLY +! RUN: %flang -ccc-print-phases -S 2>&1 -x f95-cpp-input %s | FileCheck %s --check-prefix=AONLY +! RUN: %flang -ccc-print-phases -c -emit-llvm 2>&1 -x f95-cpp-input %s | FileCheck %s --check-prefix=LLONLY +! RUN: %flang -ccc-print-phases -S -emit-llvm 2>&1 -x f95-cpp-input %s | FileCheck %s --check-prefix=LLONLY +! RUN: %flang -ccc-print-phases -fsyntax-only 2>&1 -x f95-cpp-input %s | FileCheck %s --check-prefix=SONLY +! RUN: %flang -ccc-print-phases -E 2>&1 -x f95-cpp-input %s | FileCheck %s --check-prefix=PPONLY + +! LINK-NOPP: 0: input, {{.*}}, f95 +! LINK-NOPP: 1: compiler, {0}, ir +! LINK-NOPP: 2: backend, {1}, assembler +! LINK-NOPP: 3: assembler, {2}, object +! LINK-NOPP: 4: linker, {3}, image + +! CONLY-NOPP: 0: input, {{.*}}, f95 +! CONLY-NOPP: 1: compiler, {0}, ir +! CONLY-NOPP: 2: backend, {1}, assembler +! CONLY-NOPP: 3: assembler, {2}, object +! CONLY-NOPP-NOT: 4: linker, {3}, image + +! AONLY-NOPP: 0: input, {{.*}}, f95 +! AONLY-NOPP: 1: compiler, {0}, ir +! AONLY-NOPP: 2: backend, {1}, assembler +! AONLY-NOPP-NOT: 3: assembler, {2}, object +! AONLY-NOPP-NOT: 4: linker, {3}, image + +! LLONLY-NOPP: 0: input, {{.*}}, f95 +! LLONLY-NOPP: 1: compiler, {0}, ir +! LLONLY-NOPP-NOT: 2: backend, {1}, assembler +! LLONLY-NOPP-NOT: 3: assembler, {2}, object +! LLONLY-NOPP-NOT: 4: linker, {3}, image + +! SONLY-NOPP: 0: input, {{.*}}, f95 +! SONLY-NOPP-NOT: 1: compiler, {0}, ir +! SONLY-NOPP-NOT: 2: backend, {1}, assembler +! SONLY-NOPP-NOT: 3: assembler, {2}, object +! SONLY-NOPP-NOT: 4: linker, {3}, image + +! PPONLY-NOPP: 0: input, {{.*}}, f95 +! PPONLY-NOPP: 1: compiler, {0}, ir +! PPONLY-NOPP-NOT: 2: backend, {1}, assembler +! PPONLY-NOPP-NOT: 3: assembler, {2}, object +! PPONLY-NOPP-NOT: 4: linker, {3}, image + +! LINK: 0: input, {{.*}}, f95-cpp-input +! LINK: 1: preprocessor, {0}, f95 +! LINK: 2: compiler, {1}, ir +! LINK: 3: backend, {2}, assembler +! LINK: 4: assembler, {3}, object +! LINK: 5: linker, {4}, image + +! CONLY: 0: input, {{.*}}, f95-cpp-input +! CONLY: 1: preprocessor, {0}, f95 +! CONLY: 2: compiler, {1}, ir +! CONLY: 3: backend, {2}, assembler +! CONLY: 4: assembler, {3}, object +! CONLY-NOT: 5: linker, {4}, image + +! AONLY: 0: input, {{.*}}, f95-cpp-input +! AONLY: 1: preprocessor, {0}, f95 +! AONLY: 2: compiler, {1}, ir +! AONLY: 3: backend, {2}, assembler +! AONLY-NOT: 4: assembler, {3}, object +! AONLY-NOT: 5: linker, {4}, image + +! LLONLY: 0: input, {{.*}}, f95-cpp-input +! LLONLY: 1: preprocessor, {0}, f95 +! LLONLY: 2: compiler, {1}, ir +! LLONLY-NOT: 3: backend, {2}, assembler +! LLONLY-NOT: 4: assembler, {3}, object +! LLONLY-NOT: 5: linker, {4}, image + +! SONLY: 0: input, {{.*}}, f95-cpp-input +! SONLY: 1: preprocessor, {0}, f95 +! SONLY-NOT: 2: compiler, {1}, ir +! SONLY-NOT: 3: backend, {2}, assembler +! SONLY-NOT: 4: assembler, {3}, object +! SONLY-NOT: 5: linker, {4}, image + +! PPONLY: 0: input, {{.*}}, f95-cpp-input +! PPONLY: 1: preprocessor, {0}, f95 +! PPONLY: 2: compiler, {1}, ir +! PPONLY-NOT: 3: backend, {2}, assembler +! PPONLY-NOT: 4: assembler, {3}, object +! PPONLY-NOT: 5: linker, {4}, image + +program hello + write(*, *) "Hello" +end program hello diff --git a/llvm/utils/lit/lit/TestingConfig.py b/llvm/utils/lit/lit/TestingConfig.py index 55e2a764d8fa..a69a2ee0b8fc 100644 --- a/llvm/utils/lit/lit/TestingConfig.py +++ b/llvm/utils/lit/lit/TestingConfig.py @@ -27,6 +27,7 @@ class TestingConfig(object): 'SYSTEMROOT', 'TERM', 'CLANG', + 'FLANG', 'LLDB', 'LD_PRELOAD', 'LLVM_SYMBOLIZER_PATH', diff --git a/llvm/utils/lit/lit/llvm/config.py b/llvm/utils/lit/lit/llvm/config.py index 7dae83733f31..b16e035b77ea 100644 --- a/llvm/utils/lit/lit/llvm/config.py +++ b/llvm/utils/lit/lit/llvm/config.py @@ -457,6 +457,8 @@ class LLVMConfig(object): just-built or optionally an installed clang, and add a set of standard substitutions useful to any test suite that makes use of clang. + Also sets up use of flang + """ # Clear some environment variables that might affect Clang. # @@ -544,6 +546,14 @@ class LLVMConfig(object): self.config.substitutions.append( ('%resource_dir', builtin_include_dir)) + self.config.flang = self.use_llvm_tool( + 'flang', search_env='FLANG', required=required) + if self.config.flang: + tool_substitutions = [ + ToolSubst('%flang', command=self.config.flang) + ] + self.add_tool_substitutions(tool_substitutions) + self.config.substitutions.append( ('%itanium_abi_triple', self.make_itanium_abi_triple(self.config.target_triple))) -- Gitee From cb4b2406de201f64d45ec2990497390533662f35 Mon Sep 17 00:00:00 2001 From: Bryan Chan Date: Mon, 25 Apr 2022 15:18:45 -0400 Subject: [PATCH 15/33] [LoopVectorize] Revert Classic Flang patch causing AArch64 test failure This patch partially reverts the following commit from an early version of Classic Flang LLVM: https://github.com/flang-compiler/llvm/commit/68669092a5ad1fd29f62346dc30973f86cfacbfe When the LoopVectorize.cpp change in that commit is ported to LLVM 14, it causes a failure in the following test: llvm/test/Transforms/LoopVectorize/AArch64/smallest-and-widest-types.ll Reverting the change allows all tests to run cleanly. --- llvm/lib/Transforms/Vectorize/LoopVectorize.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp index 28dce7f0857d..5fd4e45d80fb 100644 --- a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp +++ b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp @@ -5574,10 +5574,8 @@ void LoopVectorizationCostModel::collectElementTypesForWidening() { if (ValuesToIgnore.count(&I)) continue; - // Examine Loads, Stores, PHINodes - // Also examine instructions which convert to a float/double - if (!isa(I) && !isa(I) && !isa(I) && - !isa(I) && !isa(I) && !isa(I)) + // Only examine Loads, Stores and PHINodes. + if (!isa(I) && !isa(I) && !isa(I)) continue; // Examine PHI nodes that are reduction variables. Update the type to -- Gitee From 5e6d54bfacc9eb533e33f166f9069d857a566de8 Mon Sep 17 00:00:00 2001 From: Richard Barton Date: Fri, 12 Nov 2021 17:10:05 +0000 Subject: [PATCH 16/33] [driver] Pass LLVM target_features to flang Pass LLVM target features (-mattr strings) to flang to embed in generated .ll files. For normal compilation this won't make much difference as the attributes are passed to clang after flang2 and can be applied there but this is crucial to enable LTO with flang as clang will not apply the attributes when building the flang2 output. libLTO will need to read these out of the object files to apply them. Signed-off-by: Richard Barton --- clang/lib/Driver/ToolChains/Clang.cpp | 79 +---------------- clang/lib/Driver/ToolChains/ClassicFlang.cpp | 32 +++++-- clang/lib/Driver/ToolChains/CommonArgs.cpp | 90 +++++++++++++++++++- clang/lib/Driver/ToolChains/CommonArgs.h | 7 ++ clang/test/Driver/emit-flang-attrs.f90 | 11 +++ 5 files changed, 133 insertions(+), 86 deletions(-) create mode 100644 clang/test/Driver/emit-flang-attrs.f90 diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 69aa3404f58c..929b4d909c0f 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -10,7 +10,6 @@ #include "AMDGPU.h" #include "Arch/AArch64.h" #include "Arch/ARM.h" -#include "Arch/CSKY.h" #include "Arch/M68k.h" #include "Arch/Mips.h" #include "Arch/PPC.h" @@ -21,7 +20,6 @@ #include "Arch/X86.h" #include "CommonArgs.h" #include "Hexagon.h" -#include "MSP430.h" #include "PS4CPU.h" #include "clang/Basic/CLWarnings.h" #include "clang/Basic/CharInfo.h" @@ -291,87 +289,12 @@ static void ParseMPreferVectorWidth(const Driver &D, const ArgList &Args, } } -static void getWebAssemblyTargetFeatures(const ArgList &Args, - std::vector &Features) { - handleTargetFeaturesGroup(Args, Features, options::OPT_m_wasm_Features_Group); -} - static void getTargetFeatures(const Driver &D, const llvm::Triple &Triple, const ArgList &Args, ArgStringList &CmdArgs, bool ForAS, bool IsAux = false) { std::vector Features; - switch (Triple.getArch()) { - default: - break; - case llvm::Triple::mips: - case llvm::Triple::mipsel: - case llvm::Triple::mips64: - case llvm::Triple::mips64el: - mips::getMIPSTargetFeatures(D, Triple, Args, Features); - break; - case llvm::Triple::arm: - case llvm::Triple::armeb: - case llvm::Triple::thumb: - case llvm::Triple::thumbeb: - arm::getARMTargetFeatures(D, Triple, Args, Features, ForAS); - break; - - case llvm::Triple::ppc: - case llvm::Triple::ppcle: - case llvm::Triple::ppc64: - case llvm::Triple::ppc64le: - ppc::getPPCTargetFeatures(D, Triple, Args, Features); - break; - case llvm::Triple::riscv32: - case llvm::Triple::riscv64: - riscv::getRISCVTargetFeatures(D, Triple, Args, Features); - break; - case llvm::Triple::systemz: - systemz::getSystemZTargetFeatures(D, Args, Features); - break; - case llvm::Triple::aarch64: - case llvm::Triple::aarch64_32: - case llvm::Triple::aarch64_be: - aarch64::getAArch64TargetFeatures(D, Triple, Args, Features, ForAS); - break; - case llvm::Triple::x86: - case llvm::Triple::x86_64: - x86::getX86TargetFeatures(D, Triple, Args, Features); - break; - case llvm::Triple::hexagon: - hexagon::getHexagonTargetFeatures(D, Args, Features); - break; - case llvm::Triple::wasm32: - case llvm::Triple::wasm64: - getWebAssemblyTargetFeatures(Args, Features); - break; - case llvm::Triple::sparc: - case llvm::Triple::sparcel: - case llvm::Triple::sparcv9: - sparc::getSparcTargetFeatures(D, Args, Features); - break; - case llvm::Triple::r600: - case llvm::Triple::amdgcn: - amdgpu::getAMDGPUTargetFeatures(D, Triple, Args, Features); - break; - case llvm::Triple::nvptx: - case llvm::Triple::nvptx64: - NVPTX::getNVPTXTargetFeatures(D, Triple, Args, Features); - break; - case llvm::Triple::m68k: - m68k::getM68kTargetFeatures(D, Triple, Args, Features); - break; - case llvm::Triple::msp430: - msp430::getMSP430TargetFeatures(D, Args, Features); - break; - case llvm::Triple::ve: - ve::getVETargetFeatures(D, Args, Features); - break; - case llvm::Triple::csky: - csky::getCSKYTargetFeatures(D, Triple, Args, CmdArgs, Features); - break; - } + getTargetFeatureList(D, Triple, Args, CmdArgs, ForAS, Features); for (auto Feature : unifyTargetFeatures(Features)) { CmdArgs.push_back(IsAux ? "-aux-target-feature" : "-target-feature"); diff --git a/clang/lib/Driver/ToolChains/ClassicFlang.cpp b/clang/lib/Driver/ToolChains/ClassicFlang.cpp index 9c974a4df585..697357acec9f 100644 --- a/clang/lib/Driver/ToolChains/ClassicFlang.cpp +++ b/clang/lib/Driver/ToolChains/ClassicFlang.cpp @@ -59,6 +59,8 @@ class ClassicFlangMacroBuilder : public MacroBuilder { void ClassicFlang::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, const ArgList &Args, const char *LinkingOutput) const { + const Driver &D = getToolChain().getDriver(); + const llvm::Triple &Triple = getToolChain().getEffectiveTriple(); ArgStringList CommonCmdArgs; ArgStringList UpperCmdArgs; ArgStringList LowerCmdArgs; @@ -373,13 +375,13 @@ void ClassicFlang::ConstructJob(Compilation &C, const JobAction &JA, // -Mipa has no effect if (Arg *A = Args.getLastArg(options::OPT_Mipa)) { - getToolChain().getDriver().Diag(diag::warn_drv_clang_unsupported) + D.Diag(diag::warn_drv_clang_unsupported) << A->getAsString(Args); } // -Minline has no effect if (Arg *A = Args.getLastArg(options::OPT_Minline_on)) { - getToolChain().getDriver().Diag(diag::warn_drv_clang_unsupported) + D.Diag(diag::warn_drv_clang_unsupported) << A->getAsString(Args); } @@ -653,14 +655,14 @@ void ClassicFlang::ConstructJob(Compilation &C, const JobAction &JA, // Use clang's predefined macros DiagnosticsEngine DE(new DiagnosticIDs(), new DiagnosticOptions, new IgnoringDiagConsumer()); std::shared_ptr TO = std::make_shared(); - TO->Triple = getToolChain().getEffectiveTriple().getTriple(); + TO->Triple = Triple.getTriple(); std::shared_ptr TI(clang::TargetInfo::CreateTargetInfo(DE, TO)); std::string PredefineBuffer; llvm::raw_string_ostream Predefines(PredefineBuffer); ClassicFlangMacroBuilder Builder(UpperCmdArgs, Args, Predefines); LangOptions LO; - VersionTuple VT = getToolChain().computeMSVCVersion(&getToolChain().getDriver(), Args); + VersionTuple VT = getToolChain().computeMSVCVersion(&D, Args); if (!VT.empty()) { // Set the MSCompatibility version. Subminor version has 5 decimal digits. // Minor and major versions have 2 decimal digits each. @@ -690,7 +692,7 @@ void ClassicFlang::ConstructJob(Compilation &C, const JobAction &JA, DefineTypeSize("__LONG_MAX__", TargetInfo::SignedLong, *TI, Builder); // Add additional predefined macros - switch (getToolChain().getEffectiveTriple().getArch()) { + switch (Triple.getArch()) { case llvm::Triple::aarch64: UpperCmdArgs.push_back("-def"); UpperCmdArgs.push_back("__ARM_ARCH__=8"); break; @@ -784,7 +786,7 @@ void ClassicFlang::ConstructJob(Compilation &C, const JobAction &JA, Arg->claim(); UpperCmdArgs.push_back("-extend"); } else { - getToolChain().getDriver().Diag(diag::err_drv_unsupported_fixed_line_length) + D.Diag(diag::err_drv_unsupported_fixed_line_length) << Arg->getAsString(Args); } } @@ -828,7 +830,7 @@ void ClassicFlang::ConstructJob(Compilation &C, const JobAction &JA, } else if (Value == "95") { // Enable Fortran 2003 semantics UpperCmdArgs.push_back("-y"); // Unset XBIT } else { - getToolChain().getDriver().Diag(diag::err_drv_invalid_allocatable_mode) + D.Diag(diag::err_drv_invalid_allocatable_mode) << A->getAsString(Args); } } else { // No argument passed @@ -978,6 +980,22 @@ void ClassicFlang::ConstructJob(Compilation &C, const JobAction &JA, // Remove "noinline" attriblute LowerCmdArgs.push_back("-x"); LowerCmdArgs.push_back("183"); LowerCmdArgs.push_back("0x10"); + // Add target features + std::vector Features; + std::string FeatureList = ""; + getTargetFeatureList(D, Triple, Args, UpperCmdArgs, false, Features); + if (!Features.empty()) { + for (unsigned I = 0, N = Features.size(); I < N; ++I) { + StringRef Name = Features[I]; + FeatureList += Name.str(); + if (I < (N - 1)) + FeatureList += ','; + } + + LowerCmdArgs.push_back("-target_features"); + LowerCmdArgs.push_back(Args.MakeArgString(FeatureList)); + } + // Set a -x flag for second part of Fortran frontend for (Arg *A : Args.filtered(options::OPT_Mx_EQ)) { A->claim(); diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp index 3c15cc014415..723a4f7ca95d 100644 --- a/clang/lib/Driver/ToolChains/CommonArgs.cpp +++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp @@ -9,15 +9,19 @@ #include "CommonArgs.h" #include "Arch/AArch64.h" #include "Arch/ARM.h" +#include "Arch/CSKY.h" #include "Arch/M68k.h" #include "Arch/Mips.h" #include "Arch/PPC.h" +#include "Arch/RISCV.h" #include "Arch/Sparc.h" #include "Arch/SystemZ.h" #include "Arch/VE.h" #include "Arch/X86.h" -#include "HIPAMD.h" +#include "AMDGPU.h" #include "Hexagon.h" +#include "HIPAMD.h" +#include "MSP430.h" #include "clang/Basic/CharInfo.h" #include "clang/Basic/LangOptions.h" #include "clang/Basic/ObjCRuntime.h" @@ -230,6 +234,90 @@ void tools::addDirectoryList(const ArgList &Args, ArgStringList &CmdArgs, } } +static void getWebAssemblyTargetFeatures(const ArgList &Args, + std::vector &Features) { + handleTargetFeaturesGroup(Args, Features, options::OPT_m_wasm_Features_Group); +} + +void tools::getTargetFeatureList(const Driver &D, + const llvm::Triple &Triple, + const ArgList &Args, ArgStringList &CmdArgs, + bool ForAS, + std::vector &Features) { + switch (Triple.getArch()) { + default: + break; + case llvm::Triple::mips: + case llvm::Triple::mipsel: + case llvm::Triple::mips64: + case llvm::Triple::mips64el: + mips::getMIPSTargetFeatures(D, Triple, Args, Features); + break; + + case llvm::Triple::arm: + case llvm::Triple::armeb: + case llvm::Triple::thumb: + case llvm::Triple::thumbeb: + arm::getARMTargetFeatures(D, Triple, Args, Features, ForAS); + break; + + case llvm::Triple::ppc: + case llvm::Triple::ppcle: + case llvm::Triple::ppc64: + case llvm::Triple::ppc64le: + ppc::getPPCTargetFeatures(D, Triple, Args, Features); + break; + case llvm::Triple::riscv32: + case llvm::Triple::riscv64: + riscv::getRISCVTargetFeatures(D, Triple, Args, Features); + break; + case llvm::Triple::systemz: + systemz::getSystemZTargetFeatures(D, Args, Features); + break; + case llvm::Triple::aarch64: + case llvm::Triple::aarch64_32: + case llvm::Triple::aarch64_be: + aarch64::getAArch64TargetFeatures(D, Triple, Args, Features, ForAS); + break; + case llvm::Triple::x86: + case llvm::Triple::x86_64: + x86::getX86TargetFeatures(D, Triple, Args, Features); + break; + case llvm::Triple::hexagon: + hexagon::getHexagonTargetFeatures(D, Args, Features); + break; + case llvm::Triple::wasm32: + case llvm::Triple::wasm64: + getWebAssemblyTargetFeatures(Args, Features); + break; + case llvm::Triple::sparc: + case llvm::Triple::sparcel: + case llvm::Triple::sparcv9: + sparc::getSparcTargetFeatures(D, Args, Features); + break; + case llvm::Triple::r600: + case llvm::Triple::amdgcn: + amdgpu::getAMDGPUTargetFeatures(D, Triple, Args, Features); + break; + case llvm::Triple::nvptx: + case llvm::Triple::nvptx64: + NVPTX::getNVPTXTargetFeatures(D, Triple, Args, Features); + break; + case llvm::Triple::m68k: + m68k::getM68kTargetFeatures(D, Triple, Args, Features); + break; + case llvm::Triple::msp430: + msp430::getMSP430TargetFeatures(D, Args, Features); + break; + case llvm::Triple::ve: + ve::getVETargetFeatures(D, Args, Features); + break; + case llvm::Triple::csky: + csky::getCSKYTargetFeatures(D, Triple, Args, CmdArgs, Features); + break; + } +} + void tools::AddLinkerInputs(const ToolChain &TC, const InputInfoList &Inputs, const ArgList &Args, ArgStringList &CmdArgs, const JobAction &JA) { diff --git a/clang/lib/Driver/ToolChains/CommonArgs.h b/clang/lib/Driver/ToolChains/CommonArgs.h index d012f4ff8112..436d3f8f5a87 100644 --- a/clang/lib/Driver/ToolChains/CommonArgs.h +++ b/clang/lib/Driver/ToolChains/CommonArgs.h @@ -14,6 +14,7 @@ #include "clang/Driver/Multilib.h" #include "clang/Driver/Tool.h" #include "clang/Driver/ToolChain.h" +#include "llvm/Option/ArgList.h" #include "llvm/Support/CodeGen.h" namespace clang { @@ -27,6 +28,12 @@ bool needFortranLibs(const Driver &D, const llvm::opt::ArgList &Args); void addPathIfExists(const Driver &D, const Twine &Path, ToolChain::path_list &Paths); +void getTargetFeatureList(const Driver &D, + const llvm::Triple &Triple, + const llvm::opt::ArgList &Args, + llvm::opt::ArgStringList &CmdArgs, + bool ForAS, std::vector &Features); + void AddLinkerInputs(const ToolChain &TC, const InputInfoList &Inputs, const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs, const JobAction &JA); diff --git a/clang/test/Driver/emit-flang-attrs.f90 b/clang/test/Driver/emit-flang-attrs.f90 new file mode 100644 index 000000000000..91331ac227fa --- /dev/null +++ b/clang/test/Driver/emit-flang-attrs.f90 @@ -0,0 +1,11 @@ +// REQUIRES: aarch64-registered-target +// REQUIRES: classic_flang +// RUN: %flang -### -target aarch64-linux-gnu -march=armv8-a -c %s 2>&1 | FileCheck --check-prefix=CHECK-ATTRS-NEON %s +// RUN: %flang -### -target aarch64-linux-gnu -march=armv8-a+sve -c %s 2>&1 | FileCheck --check-prefix=CHECK-ATTRS-SVE %s +// RUN: %flang -### -target aarch64-linux-gnu -march=armv8-a+nosve -c %s 2>&1 | FileCheck --check-prefix=CHECK-ATTRS-NOSVE %s +// CHECK-ATTRS-NEON: "{{.*}}flang2" +// CHECK-ATTRS-NEON-SAME: "-target_features" "+neon,+v8a +// CHECK-ATTRS-SVE: "{{.*}}flang2" +// CHECK-ATTRS-SVE-SAME: "-target_features" "+neon,+v8a,+sve +// CHECK-ATTRS-NOSVE: "{{.*}}flang2" +// CHECK-ATTRS-NOSVE-SAME: "-target_features" "+neon,+v8a,-sve -- Gitee From 1e21419326017de3b3eba21eece4f1d4a5ba5569 Mon Sep 17 00:00:00 2001 From: Richard Barton Date: Thu, 18 Nov 2021 11:16:20 +0000 Subject: [PATCH 17/33] [flang-driver] Uniquify the target_features string Use existing clang support for uniquifying target feature lists to pass a unique list through to flang. --- clang/lib/Driver/ToolChains/ClassicFlang.cpp | 7 +++---- clang/test/Driver/emit-flang-attrs.f90 | 1 + 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/clang/lib/Driver/ToolChains/ClassicFlang.cpp b/clang/lib/Driver/ToolChains/ClassicFlang.cpp index 697357acec9f..03989f75b0c9 100644 --- a/clang/lib/Driver/ToolChains/ClassicFlang.cpp +++ b/clang/lib/Driver/ToolChains/ClassicFlang.cpp @@ -985,11 +985,10 @@ void ClassicFlang::ConstructJob(Compilation &C, const JobAction &JA, std::string FeatureList = ""; getTargetFeatureList(D, Triple, Args, UpperCmdArgs, false, Features); if (!Features.empty()) { - for (unsigned I = 0, N = Features.size(); I < N; ++I) { - StringRef Name = Features[I]; - FeatureList += Name.str(); - if (I < (N - 1)) + for (auto Feature : unifyTargetFeatures(Features)) { + if (!FeatureList.empty()) FeatureList += ','; + FeatureList += Feature; } LowerCmdArgs.push_back("-target_features"); diff --git a/clang/test/Driver/emit-flang-attrs.f90 b/clang/test/Driver/emit-flang-attrs.f90 index 91331ac227fa..d9a2ea954f80 100644 --- a/clang/test/Driver/emit-flang-attrs.f90 +++ b/clang/test/Driver/emit-flang-attrs.f90 @@ -3,6 +3,7 @@ // RUN: %flang -### -target aarch64-linux-gnu -march=armv8-a -c %s 2>&1 | FileCheck --check-prefix=CHECK-ATTRS-NEON %s // RUN: %flang -### -target aarch64-linux-gnu -march=armv8-a+sve -c %s 2>&1 | FileCheck --check-prefix=CHECK-ATTRS-SVE %s // RUN: %flang -### -target aarch64-linux-gnu -march=armv8-a+nosve -c %s 2>&1 | FileCheck --check-prefix=CHECK-ATTRS-NOSVE %s +// RUN: %flang -### -target aarch64-linux-gnu -march=armv8-a+sve+nosve -c %s 2>&1 | FileCheck --check-prefix=CHECK-ATTRS-NOSVE %s // CHECK-ATTRS-NEON: "{{.*}}flang2" // CHECK-ATTRS-NEON-SAME: "-target_features" "+neon,+v8a // CHECK-ATTRS-SVE: "{{.*}}flang2" -- Gitee From a4caed313ce5c04bade3f095e888768a16423079 Mon Sep 17 00:00:00 2001 From: Paul Osmialowski Date: Fri, 21 Jan 2022 10:00:58 +0000 Subject: [PATCH 18/33] [driver] Pass msve-vector-bits to flang as vscale range Signed-off-by: Paul Osmialowski --- clang/lib/Driver/ToolChains/ClassicFlang.cpp | 34 ++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/clang/lib/Driver/ToolChains/ClassicFlang.cpp b/clang/lib/Driver/ToolChains/ClassicFlang.cpp index 03989f75b0c9..80ed2d5d4383 100644 --- a/clang/lib/Driver/ToolChains/ClassicFlang.cpp +++ b/clang/lib/Driver/ToolChains/ClassicFlang.cpp @@ -995,6 +995,40 @@ void ClassicFlang::ConstructJob(Compilation &C, const JobAction &JA, LowerCmdArgs.push_back(Args.MakeArgString(FeatureList)); } + // Add vscale range + unsigned vscaleMin = 1U; + unsigned vscaleMax = 16U; + bool hasVscaleRange = false; + if (Arg *A = Args.getLastArg(options::OPT_msve_vector_bits_EQ)) { + StringRef Val = A->getValue(); + + if (Val.equals("scalable")) + hasVscaleRange = true; + else { + unsigned bits = (std::stoul(Val.str()) >> 7U); + + if ((bits < vscaleMin) || (bits > vscaleMax)) { + D.Diag(diag::warn_drv_clang_unsupported) << A->getAsString(Args); + hasVscaleRange = false; + } else { + vscaleMin = vscaleMax = bits; + hasVscaleRange = true; + } + } + } + for (auto Feature : unifyTargetFeatures(Features)) { + if (Feature.startswith("+sve")) { + hasVscaleRange = true; + break; + } + } + if (hasVscaleRange) { + LowerCmdArgs.push_back("-vscale_range_min"); + LowerCmdArgs.push_back(Args.MakeArgString(std::to_string(vscaleMin))); + LowerCmdArgs.push_back("-vscale_range_max"); + LowerCmdArgs.push_back(Args.MakeArgString(std::to_string(vscaleMax))); + } + // Set a -x flag for second part of Fortran frontend for (Arg *A : Args.filtered(options::OPT_Mx_EQ)) { A->claim(); -- Gitee From 353847cf3411b44646e6fefd65b8a4d275c7214f Mon Sep 17 00:00:00 2001 From: pwisniewskimobica Date: Thu, 13 Jan 2022 10:11:43 +0100 Subject: [PATCH 19/33] [Driver][Test] Add more variants to test/Driver/emit-flang-attrs.f90 --- clang/test/Driver/emit-flang-attrs.f90 | 70 +++++++++++++++++++++----- 1 file changed, 58 insertions(+), 12 deletions(-) diff --git a/clang/test/Driver/emit-flang-attrs.f90 b/clang/test/Driver/emit-flang-attrs.f90 index d9a2ea954f80..df23a8aa6e87 100644 --- a/clang/test/Driver/emit-flang-attrs.f90 +++ b/clang/test/Driver/emit-flang-attrs.f90 @@ -1,12 +1,58 @@ -// REQUIRES: aarch64-registered-target -// REQUIRES: classic_flang -// RUN: %flang -### -target aarch64-linux-gnu -march=armv8-a -c %s 2>&1 | FileCheck --check-prefix=CHECK-ATTRS-NEON %s -// RUN: %flang -### -target aarch64-linux-gnu -march=armv8-a+sve -c %s 2>&1 | FileCheck --check-prefix=CHECK-ATTRS-SVE %s -// RUN: %flang -### -target aarch64-linux-gnu -march=armv8-a+nosve -c %s 2>&1 | FileCheck --check-prefix=CHECK-ATTRS-NOSVE %s -// RUN: %flang -### -target aarch64-linux-gnu -march=armv8-a+sve+nosve -c %s 2>&1 | FileCheck --check-prefix=CHECK-ATTRS-NOSVE %s -// CHECK-ATTRS-NEON: "{{.*}}flang2" -// CHECK-ATTRS-NEON-SAME: "-target_features" "+neon,+v8a -// CHECK-ATTRS-SVE: "{{.*}}flang2" -// CHECK-ATTRS-SVE-SAME: "-target_features" "+neon,+v8a,+sve -// CHECK-ATTRS-NOSVE: "{{.*}}flang2" -// CHECK-ATTRS-NOSVE-SAME: "-target_features" "+neon,+v8a,-sve +! REQUIRES: aarch64-registered-target +! REQUIRES: classic_flang +! RUN: %flang -### -target aarch64-linux-gnu -march=armv8-a -c %s 2>&1 | FileCheck --check-prefix=CHECK-ATTRS-NEON %s +! RUN: %flang -### -target aarch64-linux-gnu -march=armv8-a+sve -c %s 2>&1 | FileCheck --check-prefix=CHECK-ATTRS-SVE %s +! RUN: %flang -### -target aarch64-linux-gnu -march=armv8-a+nosve -c %s 2>&1 | FileCheck --check-prefix=CHECK-ATTRS-NOSVE %s +! RUN: %flang -### -target aarch64-linux-gnu -march=armv8-a+sve+nosve -c %s 2>&1 | FileCheck --check-prefix=CHECK-ATTRS-NOSVE %s +! RUN: %flang -### -target aarch64-linux-gnu -march=armv8-a+sve2+nosve2 -c %s 2>&1 | FileCheck %s --check-prefix=CHECK-SVE2-REVERT +! RUN: %flang -### -target aarch64-linux-gnu -march=armv8-a+sve2-aes -c %s 2>&1 | FileCheck %s --check-prefix=CHECK-SVE2-AES +! RUN: %flang -### -target aarch64-linux-gnu -march=armv8-a+sve2-sm4 -c %s 2>&1 | FileCheck %s --check-prefix=CHECK-SVE2-SM4 +! RUN: %flang -### -target aarch64-linux-gnu -march=armv8-a+sve2-sha3 -c %s 2>&1 | FileCheck %s --check-prefix=CHECK-SVE2-SHA3 +! RUN: %flang -### -target aarch64-linux-gnu -march=armv8-a+sve2-bitperm+nosve2-bitperm -c %s 2>&1 | FileCheck %s --check-prefix=CHECK-SVE2-BITPERM-REVERT +! RUN: %flang -### -target aarch64-linux-gnu -march=armv8-a+sve2 -c %s 2>&1 | FileCheck %s --check-prefix=CHECK-SVE2-IMPLY +! RUN: %flang -### -target aarch64-linux-gnu -march=armv8-a+nosve+sve2 -c %s 2>&1 | FileCheck %s --check-prefix=CHECK-SVE2-CONFLICT-REV +! RUN: %flang -### -target aarch64-linux-gnu -march=armv8-a+sve+sve2 -c %s 2>&1 | FileCheck %s --check-prefix=CHECK-SVE-SVE2 +! RUN: %flang -### -target aarch64-linux-gnu -march=armv8-a+sve2-bitperm -c %s 2>&1 | FileCheck %s --check-prefix=CHECK-SVE2-BITPERM +! RUN: %flang -### -target aarch64-linux-gnu -march=armv8-a+nosve+sve2-aes -c %s 2>&1 | FileCheck %s --check-prefix=CHECK-SVE-SUBFEATURE-CONFLICT-REV +! RUN: %flang -### -target aarch64-linux-gnu -march=armv8-a+sve2-sm4+nosve2 -c %s 2>&1 | FileCheck %s --check-prefix=CHECK-SVE2-SUBFEATURE-CONFLICT +! RUN: %flang -### -target aarch64-linux-gnu -march=armv8-a+sve2-bitperm+nosve2-aes -c %s 2>&1 | FileCheck %s --check-prefix=CHECK-SVE2-SUBFEATURE-MIX +! RUN: %flang -### -target aarch64-linux-gnu -march=armv8-a+sve2-sm4+nosve2-sm4 -c %s 2>&1 | FileCheck %s --check-prefix=CHECK-SVE2-SM4-REVERT +! RUN: %flang -### -target aarch64-linux-gnu -march=armv8-a+sve2-sha3+nosve2-sha3 %s 2>&1 | FileCheck %s --check-prefix=CHECK-SVE2-SHA3-REVERT +! RUN: %flang -### -target aarch64-linux-gnu -march=armv8-a+sve2-aes+nosve2-aes %s 2>&1 | FileCheck %s --check-prefix=CHECK-SVE2-AES-REVERT + +! CHECK-ATTRS-NEON: "{{.*}}flang2" +! CHECK-ATTRS-NEON-SAME: "-target_features" "+neon,+v8a" +! CHECK-ATTRS-SVE: "{{.*}}flang2" +! CHECK-ATTRS-SVE-SAME: "-target_features" "+neon,+v8a,+sve" +! CHECK-ATTRS-NOSVE: "{{.*}}flang2" +! CHECK-ATTRS-NOSVE-SAME: "-target_features" "+neon,+v8a,-sve,-sve2,-sve2-bitperm,-sve2-sha3,-sve2-aes,-sve2-sm4" +! CHECK-SVE2-REVERT: "{{.*}}flang2" +! CHECK-SVE2-REVERT-SAME: "-target_features" "+neon,+v8a,+sve,-sve2,-sve2-bitperm,-sve2-sha3,-sve2-aes,-sve2-sm4" +! CHECK-SVE2-AES: "{{.*}}flang2" +! CHECK-SVE2-AES-SAME: "-target_features" "+neon,+v8a,+sve2-aes,+sve,+sve2" +! CHECK-SVE2-SM4: "{{.*}}flang2" +! CHECK-SVE2-SM4-SAME: "-target_features" "+neon,+v8a,+sve2-sm4,+sve,+sve2" +! CHECK-SVE2-SHA3: "{{.*}}flang2" +! CHECK-SVE2-SHA3-SAME: "-target_features" "+neon,+v8a,+sve2-sha3,+sve,+sve2" +! CHECK-SVE2-BITPERM-REVERT: "{{.*}}flang2" +! CHECK-SVE2-BITPERM-REVERT-SAME: "-target_features" "+neon,+v8a,+sve,+sve2,-sve2-bitperm" +! CHECK-SVE2-IMPLY: "{{.*}}flang2" +! CHECK-SVE2-IMPLY-SAME: "-target_features" "+neon,+v8a,+sve2,+sve" +! CHECK-SVE2-CONFLICT-REV: "{{.*}}flang2" +! CHECK-SVE2-CONFLICT-REV-SAME: "-target_features" "+neon,+v8a,-sve2-bitperm,-sve2-sha3,-sve2-aes,-sve2-sm4,+sve2,+sve" +! CHECK-SVE-SVE2: "{{.*}}flang2" +! CHECK-SVE-SVE2-SAME: "-target_features" "+neon,+v8a,+sve2,+sve" +! CHECK-SVE2-BITPERM: "{{.*}}flang2" +! CHECK-SVE2-BITPERM-SAME: "-target_features" "+neon,+v8a,+sve2-bitperm,+sve,+sve2" +! CHECK-SVE-SUBFEATURE-CONFLICT-REV: "{{.*}}flang2" +! CHECK-SVE-SUBFEATURE-CONFLICT-REV-SAME: "-target_features" "+neon,+v8a,-sve2-bitperm,-sve2-sha3,-sve2-sm4,+sve2-aes,+sve,+sve2" +! CHECK-SVE2-SUBFEATURE-CONFLICT: "{{.*}}flang2" +! CHECK-SVE2-SUBFEATURE-CONFLICT-SAME: "-target_features" "+neon,+v8a,+sve,-sve2,-sve2-bitperm,-sve2-sha3,-sve2-aes,-sve2-sm4" +! CHECK-SVE2-SUBFEATURE-MIX: "{{.*}}flang2" +! CHECK-SVE2-SUBFEATURE-MIX-SAME: "-target_features" "+neon,+v8a,+sve2-bitperm,+sve,+sve2,-sve2-aes" +! CHECK-SVE2-SM4-REVERT: "{{.*}}flang2" +! CHECK-SVE2-SM4-REVERT-SAME: "-target_features" "+neon,+v8a,+sve,+sve2,-sve2-sm4" +! CHECK-SVE2-SHA3-REVERT: "{{.*}}flang2" +! CHECK-SVE2-SHA3-REVERT-SAME: "-target_features" "+neon,+v8a,+sve,+sve2,-sve2-sha3" +! CHECK-SVE2-AES-REVERT: "{{.*}}flang2" +! CHECK-SVE2-AES-REVERT-SAME: "-target_features" "+neon,+v8a,+sve,+sve2,-sve2-aes" -- Gitee From 7d216add1ae31d6fd12548c965f340b8f58cb750 Mon Sep 17 00:00:00 2001 From: Richard Barton Date: Tue, 22 Mar 2022 09:26:00 +0000 Subject: [PATCH 20/33] Fix classic flang version screen Version screen has been erroneously reporting as flang-new since LLVM 12 --- clang/lib/Driver/Driver.cpp | 4 ++++ clang/test/Driver/flang/classic-flang-version.f | 3 +++ 2 files changed, 7 insertions(+) create mode 100644 clang/test/Driver/flang/classic-flang-version.f diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp index 386919d1c436..925be5216af3 100644 --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -1820,7 +1820,11 @@ void Driver::PrintHelp(bool ShowHidden) const { void Driver::PrintVersion(const Compilation &C, raw_ostream &OS) const { if (IsFlangMode()) { +#ifdef ENABLE_CLASSIC_FLANG + OS << getClangToolFullVersion("flang") << '\n'; +#else OS << getClangToolFullVersion("flang-new") << '\n'; +#endif } else { // FIXME: The following handlers should use a callback mechanism, we don't // know what the client would like to do. diff --git a/clang/test/Driver/flang/classic-flang-version.f b/clang/test/Driver/flang/classic-flang-version.f new file mode 100644 index 000000000000..c2082d3af8b7 --- /dev/null +++ b/clang/test/Driver/flang/classic-flang-version.f @@ -0,0 +1,3 @@ +! REQUIRES: classic-flang +! RUN: %flang --version | FileCheck %s +! CHECK: flang version {{.*}} ({{.*}}flang-compiler/classic-flang-llvm-project.git {{.*}}) -- Gitee From c199beb0b57e083f4e67fb493ec1173b2de3c103 Mon Sep 17 00:00:00 2001 From: Richard Barton Date: Fri, 18 Mar 2022 16:47:15 +0000 Subject: [PATCH 21/33] Canonicalize some ENABLE_CLASSIC_FLANG These CMake variables are used to set python variables in the lit config. As such, they need to bet set with a valid CMake boolean value that is also a valid python boolean value (1, True, etc.) and not one that is not (ON, NO, etc.) to work. This is fragile. Call the LLVM cmake helper function on these two downstream CMake --- clang/test/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/clang/test/CMakeLists.txt b/clang/test/CMakeLists.txt index 5b604b2a3eeb..3f48aba1d6f4 100644 --- a/clang/test/CMakeLists.txt +++ b/clang/test/CMakeLists.txt @@ -10,6 +10,7 @@ llvm_canonicalize_cmake_booleans( CLANG_PLUGIN_SUPPORT CLANG_SPAWN_CC1 ENABLE_BACKTRACES + LLVM_ENABLE_CLASSIC_FLANG LLVM_ENABLE_ZLIB LLVM_ENABLE_PER_TARGET_RUNTIME_DIR LLVM_ENABLE_THREADS -- Gitee From d0bc3eaeac4287c1d7085395bc40dbc8ec63474d Mon Sep 17 00:00:00 2001 From: Richard Barton Date: Fri, 18 Mar 2022 16:44:23 +0000 Subject: [PATCH 22/33] [NFC] Add missing ENABLE_CLASSIC_FLANG guard. Signed-off-by: Richard Barton --- clang/lib/Driver/Driver.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp index 925be5216af3..f71e7894be96 100644 --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -5086,9 +5086,11 @@ class ToolSelector final { if (!T->hasIntegratedBackend() && !(OutputIsLLVM && T->canEmitIR())) return nullptr; +#ifdef ENABLE_CLASSIC_FLANG // Classic Flang is not integrated with the backend. if (C.getDriver().IsFlangMode() && !T->hasIntegratedAssembler()) return nullptr; +#endif if (T->canEmitIR() && ((SaveTemps && !InputIsBitcode) || EmbedBitcode)) return nullptr; -- Gitee From 6083e5cb8574e5aa16c6a1b5d38964c5c7370fcb Mon Sep 17 00:00:00 2001 From: Richard Barton Date: Tue, 3 May 2022 17:38:49 +0100 Subject: [PATCH 23/33] Fix flang driver preprocessor issue Fix a bug where flang -E -save-temps input.F90 would preprocess the input file twice. Add a new test for preprocessor behaviour that would expose the bug and updated fortran-phases test for new behaviour. Also added -emit-flang-llvm to that test for completeness. Signed-off-by: Richard Barton --- clang/lib/Driver/Driver.cpp | 23 +++--- clang/lib/Driver/ToolChains/ClassicFlang.cpp | 4 +- clang/test/Driver/fortran-phases.f90 | 73 ++++++++++++-------- clang/test/Driver/fortran-preprocessor.f90 | 47 +++++++++++++ 4 files changed, 109 insertions(+), 38 deletions(-) create mode 100644 clang/test/Driver/fortran-preprocessor.f90 diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp index f71e7894be96..5e239fd8fdec 100644 --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -337,14 +337,7 @@ phases::ID Driver::getFinalPhase(const DerivedArgList &DAL, (PhaseArg = DAL.getLastArg(options::OPT_M, options::OPT_MM)) || (PhaseArg = DAL.getLastArg(options::OPT__SLASH_P)) || CCGenDiagnostics) { -#ifdef ENABLE_CLASSIC_FLANG - if (IsFlangMode()) - FinalPhase = phases::Compile; - else - FinalPhase = phases::Preprocess; -#else FinalPhase = phases::Preprocess; -#endif // --precompile only runs up to precompilation. // Options that cause the output of C++20 compiled module interfaces or @@ -2497,7 +2490,11 @@ void Driver::BuildInputs(const ToolChain &TC, DerivedArgList &Args, if (memcmp(Value, "-", 2) == 0) { if (IsFlangMode()) { #ifdef ENABLE_CLASSIC_FLANG - Ty = types::TY_C; + // If running with -E, treat as needing preprocessing + if (!Args.hasArgNoClaim(options::OPT_E)) + Ty = types::TY_PP_F_FreeForm; + else + Ty = types::TY_F_FreeForm; #else Ty = types::TY_Fortran; #endif @@ -2522,6 +2519,16 @@ void Driver::BuildInputs(const ToolChain &TC, DerivedArgList &Args, // idea of what .s is. if (const char *Ext = strrchr(Value, '.')) Ty = TC.LookupTypeForExtension(Ext + 1); +#ifdef ENABLE_CLASSIC_FLANG + // If called with -E, treat the inputs as needing preprocessing + // regardless of extension + if (IsFlangMode() && Args.hasArgNoClaim(options::OPT_E)) { + if (Ty == types::TY_PP_F_FreeForm) + Ty = types::TY_F_FreeForm; + else if (Ty == types::TY_PP_F_FixedForm) + Ty = types::TY_F_FixedForm; + } +#endif if (Ty == types::TY_INVALID) { if (IsCLMode() && (Args.hasArgNoClaim(options::OPT_E) || CCGenDiagnostics)) diff --git a/clang/lib/Driver/ToolChains/ClassicFlang.cpp b/clang/lib/Driver/ToolChains/ClassicFlang.cpp index 80ed2d5d4383..2fe317a3d003 100644 --- a/clang/lib/Driver/ToolChains/ClassicFlang.cpp +++ b/clang/lib/Driver/ToolChains/ClassicFlang.cpp @@ -79,8 +79,8 @@ void ClassicFlang::ConstructJob(Compilation &C, const JobAction &JA, // Check file type sanity assert(types::isAcceptedByFlang(InputType) && "Can only accept Fortran"); - if (Args.hasArg(options::OPT_fsyntax_only)) { - // For -fsyntax-only produce temp files only + if (Args.hasArg(options::OPT_fsyntax_only, options::OPT_E)) { + // For -fsyntax-only and -E produce temp files only Stem = C.getDriver().GetTemporaryPath("", ""); } else { OutFile = Output.getFilename(); diff --git a/clang/test/Driver/fortran-phases.f90 b/clang/test/Driver/fortran-phases.f90 index 5a79bb26bcde..57d5f2c92b78 100644 --- a/clang/test/Driver/fortran-phases.f90 +++ b/clang/test/Driver/fortran-phases.f90 @@ -7,6 +7,7 @@ ! RUN: %flang -ccc-print-phases -S 2>&1 %s | FileCheck %s --check-prefix=AONLY-NOPP ! RUN: %flang -ccc-print-phases -c -emit-llvm 2>&1 %s | FileCheck %s --check-prefix=LLONLY-NOPP ! RUN: %flang -ccc-print-phases -S -emit-llvm 2>&1 %s | FileCheck %s --check-prefix=LLONLY-NOPP +! RUN: %flang -ccc-print-phases -emit-flang-llvm 2>&1 %s | FileCheck %s --check-prefix=FLLONLY-NOPP ! RUN: %flang -ccc-print-phases -fsyntax-only 2>&1 %s | FileCheck %s --check-prefix=SONLY-NOPP ! RUN: %flang -ccc-print-phases -E 2>&1 %s | FileCheck %s --check-prefix=PPONLY-NOPP @@ -16,6 +17,7 @@ ! RUN: %flang -ccc-print-phases -S 2>&1 -x f95-cpp-input %s | FileCheck %s --check-prefix=AONLY ! RUN: %flang -ccc-print-phases -c -emit-llvm 2>&1 -x f95-cpp-input %s | FileCheck %s --check-prefix=LLONLY ! RUN: %flang -ccc-print-phases -S -emit-llvm 2>&1 -x f95-cpp-input %s | FileCheck %s --check-prefix=LLONLY +! RUN: %flang -ccc-print-phases -emit-flang-llvm 2>&1 -x f95-cpp-input %s | FileCheck %s --check-prefix=FLLONLY ! RUN: %flang -ccc-print-phases -fsyntax-only 2>&1 -x f95-cpp-input %s | FileCheck %s --check-prefix=SONLY ! RUN: %flang -ccc-print-phases -E 2>&1 -x f95-cpp-input %s | FileCheck %s --check-prefix=PPONLY @@ -29,31 +31,39 @@ ! CONLY-NOPP: 1: compiler, {0}, ir ! CONLY-NOPP: 2: backend, {1}, assembler ! CONLY-NOPP: 3: assembler, {2}, object -! CONLY-NOPP-NOT: 4: linker, {3}, image +! CONLY-NOPP-NOT: {{.*}}: linker, {{{.*}}}, image ! AONLY-NOPP: 0: input, {{.*}}, f95 ! AONLY-NOPP: 1: compiler, {0}, ir ! AONLY-NOPP: 2: backend, {1}, assembler -! AONLY-NOPP-NOT: 3: assembler, {2}, object -! AONLY-NOPP-NOT: 4: linker, {3}, image +! AONLY-NOPP-NOT: {{.*}}: assembler, {{{.*}}}, object +! AONLY-NOPP-NOT: {{.*}}: linker, {{{.*}}}, image ! LLONLY-NOPP: 0: input, {{.*}}, f95 ! LLONLY-NOPP: 1: compiler, {0}, ir -! LLONLY-NOPP-NOT: 2: backend, {1}, assembler -! LLONLY-NOPP-NOT: 3: assembler, {2}, object -! LLONLY-NOPP-NOT: 4: linker, {3}, image +! LLONLY-NOPP-NOT: {{.*}}: backend, {{{.*}}}, assembler +! LLONLY-NOPP-NOT: {{.*}}: assembler, {{{.*}}}, object +! LLONLY-NOPP-NOT: {{.*}}: linker, {{{.*}}}, image + +! FLLONLY-NOPP: 0: input, {{.*}}, f95 +! FLLONLY-NOPP: 1: compiler, {0}, ir +! FLLONLY-NOPP-NOT: {{.*}}: backend, {{{.*}}}, assembler +! FLLONLY-NOPP-NOT: {{.*}}: assembler, {{{.*}}}, object +! FLLONLY-NOPP-NOT: {{.*}}: linker, {{{.*}}}, image ! SONLY-NOPP: 0: input, {{.*}}, f95 -! SONLY-NOPP-NOT: 1: compiler, {0}, ir -! SONLY-NOPP-NOT: 2: backend, {1}, assembler -! SONLY-NOPP-NOT: 3: assembler, {2}, object -! SONLY-NOPP-NOT: 4: linker, {3}, image +! SONLY-NOPP-NOT: {{.*}}: compiler, {{{.*}}}, ir +! SONLY-NOPP-NOT: {{.*}}: backend, {{{.*}}}, assembler +! SONLY-NOPP-NOT: {{.*}}: assembler, {{{.*}}}, object +! SONLY-NOPP-NOT: {{.*}}: linker, {{{.*}}}, image +! flang always preprocesses with -E regardless of file extension ! PPONLY-NOPP: 0: input, {{.*}}, f95 -! PPONLY-NOPP: 1: compiler, {0}, ir -! PPONLY-NOPP-NOT: 2: backend, {1}, assembler -! PPONLY-NOPP-NOT: 3: assembler, {2}, object -! PPONLY-NOPP-NOT: 4: linker, {3}, image +! PPONLY-NOPP: 1: preprocessor, {0}, f95 +! PPONLY-NOPP-NOT: {{.*}}: compiler, {{{.*}}}, ir +! PPONLY-NOPP-NOT: {{.*}}: backend, {{{.*}}}, assembler +! PPONLY-NOPP-NOT: {{.*}}: assembler, {{{.*}}}, object +! PPONLY-NOPP-NOT: {{.*}}: linker, {{{.*}}}, image ! LINK: 0: input, {{.*}}, f95-cpp-input ! LINK: 1: preprocessor, {0}, f95 @@ -67,35 +77,42 @@ ! CONLY: 2: compiler, {1}, ir ! CONLY: 3: backend, {2}, assembler ! CONLY: 4: assembler, {3}, object -! CONLY-NOT: 5: linker, {4}, image +! CONLY-NOT: {{.*}}: linker, {{{.*}}}, image ! AONLY: 0: input, {{.*}}, f95-cpp-input ! AONLY: 1: preprocessor, {0}, f95 ! AONLY: 2: compiler, {1}, ir ! AONLY: 3: backend, {2}, assembler -! AONLY-NOT: 4: assembler, {3}, object -! AONLY-NOT: 5: linker, {4}, image +! AONLY-NOT: {{.*}}: assembler, {{{.*}}}, object +! AONLY-NOT: {{.*}}: linker, {{{.*}}}, image ! LLONLY: 0: input, {{.*}}, f95-cpp-input ! LLONLY: 1: preprocessor, {0}, f95 ! LLONLY: 2: compiler, {1}, ir -! LLONLY-NOT: 3: backend, {2}, assembler -! LLONLY-NOT: 4: assembler, {3}, object -! LLONLY-NOT: 5: linker, {4}, image +! LLONLY-NOT: {{.*}}: backend, {{{.*}}}, assembler +! LLONLY-NOT: {{.*}}: assembler, {{{.*}}}, object +! LLONLY-NOT: {{.*}}: linker, {{{.*}}}, image + +! FLLONLY: 0: input, {{.*}}, f95-cpp-input +! FLLONLY: 1: preprocessor, {0}, f95 +! FLLONLY: 2: compiler, {1}, ir +! FLLONLY-NOT: {{.*}}: backend, {{{.*}}}, assembler +! FLLONLY-NOT: {{.*}}: assembler, {{{.*}}}, object +! FLLONLY-NOT: {{.*}}: linker, {{{.*}}}, image ! SONLY: 0: input, {{.*}}, f95-cpp-input ! SONLY: 1: preprocessor, {0}, f95 -! SONLY-NOT: 2: compiler, {1}, ir -! SONLY-NOT: 3: backend, {2}, assembler -! SONLY-NOT: 4: assembler, {3}, object -! SONLY-NOT: 5: linker, {4}, image +! SONLY-NOT: {{.*}}: compiler, {{{.*}}}, ir +! SONLY-NOT: {{.*}}: backend, {{{.*}}}, assembler +! SONLY-NOT: {{.*}}: assembler, {{{.*}}}, object +! SONLY-NOT: {{.*}}: linker, {{{.*}}}, image ! PPONLY: 0: input, {{.*}}, f95-cpp-input ! PPONLY: 1: preprocessor, {0}, f95 -! PPONLY: 2: compiler, {1}, ir -! PPONLY-NOT: 3: backend, {2}, assembler -! PPONLY-NOT: 4: assembler, {3}, object -! PPONLY-NOT: 5: linker, {4}, image +! PPONLY-NOT: {{.*}}: compiler, {{{.*}}}, ir +! PPONLY-NOT: {{.*}}: backend, {{{.*}}}, assembler +! PPONLY-NOT: {{.*}}: assembler, {{{.*}}}, object +! PPONLY-NOT: {{.*}}: linker, {{{.*}}}, image program hello write(*, *) "Hello" diff --git a/clang/test/Driver/fortran-preprocessor.f90 b/clang/test/Driver/fortran-preprocessor.f90 new file mode 100644 index 000000000000..99f4186ba83c --- /dev/null +++ b/clang/test/Driver/fortran-preprocessor.f90 @@ -0,0 +1,47 @@ +! REQUIRES: classic_flang + +! -cpp should preprocess as it goes, regardless of input file extension +! RUN: %flang -cpp -c -DHELLO="hello all" -### %s 2>&1 | FileCheck %s --check-prefixes=ALL,CPP,PP +! RUN: %flang -cpp -c -DHELLO="hello all" -### -c f95-cpp-input %s 2>&1 | FileCheck %s --check-prefixes=ALL,CPP,PP +! -E should preprocess then stop, regardless of input file extension +! RUN: %flang -E -DHELLO="hello all" -### %s 2>&1 | FileCheck %s --check-prefixes=ALL,E,PPONLY +! RUN: %flang -E -DHELLO="hello all" -### -x f95-cpp-input %s 2>&1 | FileCheck %s --check-prefixes=ALL,E,PPONLY +! -cpp and -E are redundant +! RUN: %flang -E -cpp -DHELLO="hello all" -### %s 2>&1 | FileCheck %s --check-prefixes=ALL,E,PPONLY + +! Don't link when given linker input +! RUN: %flang -E -cpp -Wl,-rpath=blah -### %s 2>&1 | FileCheck %s --check-prefixes=ALL,E,PPONLY + +! Explicitly test this nonsence case causing a bug with LLVM 13/14 +! RUN: %flang -E -traditional-cpp -DHELLO="hello all" -x f95-cpp-input -### %s 2>&1 | FileCheck %s --check-prefixes=ALL,E,PPONLY + +! Test -save-temps does not break things (same codepath as -traditional-cpp bug above) +! RUN: %flang -E -DHELLO="hello all" -save-temps -### %s 2>&1 | FileCheck %s --check-prefixes=ALL,E,PPONLY +! RUN: %flang -E -DHELLO="hello all" -save-temps -### -c f95-cpp-input %s 2>&1 | FileCheck %s --check-prefixes=ALL,E,PPONLY +! RUN: %flang -cpp -c -DHELLO="hello all" -save-temps -### %s 2>&1 | FileCheck %s --check-prefixes=ALL,CPP +! RUN: %flang -cpp -c -DHELLO="hello all" -save-temps -### -c f95-cpp-input %s 2>&1 | FileCheck %s --check-prefixes=ALL,CPP + +! Test for the correct cmdline flags +! Consume up to flang1 line +! ALL-LABEL: "{{.*}}flang1" +! CPP-NOT: "-es" +! CPP: "-preprocess" +! CPP-NOT: "-es" + +! E-DAG: "-es" +! E-DAG: "-preprocess" + +! flang1 should only be called once! +! ALL-NOT: "{{.*}}flang1" + +! CPP should continue to build object +! PP: "{{.*}}flang2" +! PPONLY-NOT: "{{.*}}flang2" + +! These commands should never call a linker! +! ALL-NOT: "{{.*}}ld" + +program hello + write(*, *) HELLO +end program hello + -- Gitee From 699831b124195240130e3bb0863b8c950236a048 Mon Sep 17 00:00:00 2001 From: Paul Osmialowski Date: Fri, 15 Jul 2022 09:17:08 +0100 Subject: [PATCH 24/33] classic flang: enable IEEE by default (and sort Lower/Common inconsistency out) Signed-off-by: Paul Osmialowski --- clang/lib/Driver/ToolChains/ClassicFlang.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/clang/lib/Driver/ToolChains/ClassicFlang.cpp b/clang/lib/Driver/ToolChains/ClassicFlang.cpp index 2fe317a3d003..e69c019feff2 100644 --- a/clang/lib/Driver/ToolChains/ClassicFlang.cpp +++ b/clang/lib/Driver/ToolChains/ClassicFlang.cpp @@ -66,7 +66,7 @@ void ClassicFlang::ConstructJob(Compilation &C, const JobAction &JA, ArgStringList LowerCmdArgs; SmallString<256> Stem; std::string OutFile; - bool NeedIEEE = false; + bool NeedIEEE = true; bool NeedFastMath = false; bool NeedRelaxedMath = false; @@ -555,7 +555,7 @@ void ClassicFlang::ConstructJob(Compilation &C, const JobAction &JA, LowerCmdArgs.push_back("-x"); LowerCmdArgs.push_back("216"); LowerCmdArgs.push_back("1"); - // Lower: -ieee 0 + // Common: -ieee 0 CommonCmdArgs.push_back("-ieee"); CommonCmdArgs.push_back("0"); } else if (NeedIEEE) { @@ -583,7 +583,7 @@ void ClassicFlang::ConstructJob(Compilation &C, const JobAction &JA, LowerCmdArgs.push_back("-y"); LowerCmdArgs.push_back("216"); LowerCmdArgs.push_back("1"); - // Lower: -ieee 1 + // Common: -ieee 1 CommonCmdArgs.push_back("-ieee"); CommonCmdArgs.push_back("1"); } else if (NeedRelaxedMath) { @@ -595,11 +595,11 @@ void ClassicFlang::ConstructJob(Compilation &C, const JobAction &JA, LowerCmdArgs.push_back("-y"); LowerCmdArgs.push_back("216"); LowerCmdArgs.push_back("1"); - // Lower: -ieee 0 + // Common: -ieee 0 CommonCmdArgs.push_back("-ieee"); CommonCmdArgs.push_back("0"); } else { - // Lower: -ieee 0 + // Common: -ieee 0 CommonCmdArgs.push_back("-ieee"); CommonCmdArgs.push_back("0"); } -- Gitee From 52734992f5b65da80a5addb03533a0e6e570bcab Mon Sep 17 00:00:00 2001 From: Kiran Chandramohan Date: Tue, 8 May 2018 17:49:59 +0100 Subject: [PATCH 25/33] Changes to flang's fp-contract behaviour 1) All fma and contraction behvaviour follows from the -ffp-contract= flag setting. 2) At optimization level 0, -ffp-contract=fast flag will not be honoured. 3) At all other levels, -ffp-contract=fast will be the default behaviour and the flag is honoured. --- clang/lib/Driver/ToolChains/ClassicFlang.cpp | 75 +++++++++++++------ .../flang/classic-flang-fp-contract.f95 | 27 +++++++ 2 files changed, 80 insertions(+), 22 deletions(-) create mode 100644 clang/test/Driver/flang/classic-flang-fp-contract.f95 diff --git a/clang/lib/Driver/ToolChains/ClassicFlang.cpp b/clang/lib/Driver/ToolChains/ClassicFlang.cpp index e69c019feff2..e14bda862c99 100644 --- a/clang/lib/Driver/ToolChains/ClassicFlang.cpp +++ b/clang/lib/Driver/ToolChains/ClassicFlang.cpp @@ -464,28 +464,6 @@ void ClassicFlang::ConstructJob(Compilation &C, const JobAction &JA, } } - // Enable FMA - for (Arg *A: Args.filtered(options::OPT_Mfma_on, options::OPT_fma)) { - A->claim(); - LowerCmdArgs.push_back("-x"); - LowerCmdArgs.push_back("172"); - LowerCmdArgs.push_back("0x40000000"); - LowerCmdArgs.push_back("-x"); - LowerCmdArgs.push_back("179"); - LowerCmdArgs.push_back("1"); - } - - // Disable FMA - for (Arg *A: Args.filtered(options::OPT_Mfma_off, options::OPT_nofma)) { - A->claim(); - LowerCmdArgs.push_back("-x"); - LowerCmdArgs.push_back("171"); - LowerCmdArgs.push_back("0x40000000"); - LowerCmdArgs.push_back("-x"); - LowerCmdArgs.push_back("178"); - LowerCmdArgs.push_back("1"); - } - // For -fPIC set -x 62 8 for second part of Fortran frontend for (Arg *A: Args.filtered(options::OPT_fPIC)) { A->claim(); @@ -550,6 +528,59 @@ void ClassicFlang::ConstructJob(Compilation &C, const JobAction &JA, A->claim(); } + // fp-contract=fast is the default + bool EnableFPContraction = true; + if (Arg *A = Args.getLastArg(options::OPT_ffp_contract, + options::OPT_Mfma_on, + options::OPT_fma, + options::OPT_Mfma_off, + options::OPT_nofma)) { + auto Opt = A->getOption(); + if (Opt.matches(options::OPT_ffp_contract)) { + StringRef Val = A->getValue(); + if ((Val == "fast") || (Val == "on")) { + EnableFPContraction = true; + } else if (Val == "off") { + EnableFPContraction = false; + } else { + D.Diag(diag::err_drv_unsupported_option_argument) + << A->getOption().getName() << Val; + } + } else if(Opt.matches(options::OPT_Mfma_on) || + Opt.matches(options::OPT_fma)) { + EnableFPContraction = true; + } else { + EnableFPContraction = false; + } + } + + if(OptLevel == 0) + EnableFPContraction = false; + + // Emit contract math instructions. + // Step 1 : Generate fma instructions in flang (can override with fma flag) + // Step 2 : Propagate fma contract information to LLVM to further + // exploit contraction opportunities + if (EnableFPContraction) { + LowerCmdArgs.push_back("-x"); + LowerCmdArgs.push_back("172"); + LowerCmdArgs.push_back("0x40000000"); + LowerCmdArgs.push_back("-x"); + LowerCmdArgs.push_back("179"); + LowerCmdArgs.push_back("1"); + // Step 2 + LowerCmdArgs.push_back("-x"); + LowerCmdArgs.push_back("216"); + LowerCmdArgs.push_back("0x1000"); + } else { + LowerCmdArgs.push_back("-x"); + LowerCmdArgs.push_back("171"); + LowerCmdArgs.push_back("0x40000000"); + LowerCmdArgs.push_back("-x"); + LowerCmdArgs.push_back("178"); + LowerCmdArgs.push_back("1"); + } + if (NeedFastMath) { // Lower: -x 216 1 LowerCmdArgs.push_back("-x"); diff --git a/clang/test/Driver/flang/classic-flang-fp-contract.f95 b/clang/test/Driver/flang/classic-flang-fp-contract.f95 new file mode 100644 index 000000000000..b181065d1cac --- /dev/null +++ b/clang/test/Driver/flang/classic-flang-fp-contract.f95 @@ -0,0 +1,27 @@ +! REQUIRES: classic_flang + +! RUN: %flang -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-FLANG2-FP-CONTRACT-ABSENCE +! RUN: %flang -O1 -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-FLANG2-FP-CONTRACT +! RUN: %flang -O2 -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-FLANG2-FP-CONTRACT +! RUN: %flang -O3 -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-FLANG2-FP-CONTRACT +! RUN: %flang -Ofast -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-FLANG2-FP-CONTRACT +! RUN: %flang -ffp-contract=fast -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-FLANG2-FP-CONTRACT-ABSENCE +! RUN: %flang -O1 -ffp-contract=fast -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-FLANG2-FP-CONTRACT +! RUN: %flang -O2 -ffp-contract=fast -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-FLANG2-FP-CONTRACT +! RUN: %flang -O3 -ffp-contract=fast -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-FLANG2-FP-CONTRACT +! RUN: %flang -Ofast -ffp-contract=fast -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-FLANG2-FP-CONTRACT +! RUN: %flang -ffp-contract=on -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-FLANG2-FP-CONTRACT-ABSENCE +! RUN: %flang -O1 -ffp-contract=on -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-FLANG2-FP-CONTRACT +! RUN: %flang -O2 -ffp-contract=on -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-FLANG2-FP-CONTRACT +! RUN: %flang -O3 -ffp-contract=on -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-FLANG2-FP-CONTRACT +! RUN: %flang -Ofast -ffp-contract=on -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-FLANG2-FP-CONTRACT +! RUN: %flang -ffp-contract=off -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-FLANG2-FP-CONTRACT-ABSENCE +! RUN: %flang -O1 -ffp-contract=off -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-FLANG2-FP-CONTRACT-ABSENCE +! RUN: %flang -O2 -ffp-contract=off -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-FLANG2-FP-CONTRACT-ABSENCE +! RUN: %flang -O3 -ffp-contract=off -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-FLANG2-FP-CONTRACT-ABSENCE +! RUN: %flang -Ofast -ffp-contract=off -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-FLANG2-FP-CONTRACT-ABSENCE + +! CHECK-FLANG2-FP-CONTRACT: "{{.*}}flang2" +! CHECK-FLANG2-FP-CONTRACT-SAME: "-x" "172" "0x40000000" "-x" "179" "1" "-x" "216" "0x1000" +! CHECK-FLANG2-FP-CONTRACT-ABSENCE: "{{.*}}flang2" +! CHECK-FLANG2-FP-CONTRACT-ABSENCE-SAME: "-x" "171" "0x40000000" "-x" "178" "1" -- Gitee From bbc4d8bf5fd5c93930a735f75a4cd8d23fb04766 Mon Sep 17 00:00:00 2001 From: Peixin-Qiao Date: Mon, 8 Aug 2022 15:03:08 +0800 Subject: [PATCH 26/33] [Driver] Remove the "-lompstub" in the driver In some workloads, users get "-lompstub" by running "flang -v" and link it explicitly, which may cause failure when compiling programs with OpenMP (flang -fopenmp test.f90 -lompstub). There is no runtime call in ompstub.c generated when "-fopenmp" is not added to compile the program. When "-fopenmp" is added to compile the program, the runtime in llvm/openmp(libomp.so) will be used. If users use some runtime library routines such as "omp_get_thread_num" and compiles it without the option "-fopenmp", both gfortran and ifort report errors of "undefined reference to ...". After remove "-lompstub" in the driver, classic-flang reports the error, too. So, it's safe to remove the "-lompstub" in the driver. --- clang/lib/Driver/ToolChain.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp index 86b778cce97a..56ff77367570 100644 --- a/clang/lib/Driver/ToolChain.cpp +++ b/clang/lib/Driver/ToolChain.cpp @@ -1068,8 +1068,6 @@ void ToolChain::AddFortranStdlibLibArgs(const ArgList &Args, CmdArgs.push_back("-lpgmath"); if (useOpenMP) CmdArgs.push_back("-lomp"); - else - CmdArgs.push_back("-lompstub"); if (staticFlangLibs) CmdArgs.push_back("-Bdynamic"); -- Gitee From 8acdfb473bd56bbdb93c68a6f8a8ec17bbde6c77 Mon Sep 17 00:00:00 2001 From: Bryan Chan Date: Sat, 10 Sep 2022 19:41:06 -0400 Subject: [PATCH 27/33] [Driver] Pass Classic Flang libraries to the linker correctly In LLVM 15, the Fortran and OpenMP runtime libraries are added to the linker command line using common methods (addFortranRuntime* and addOpenMPRuntime*). This commit adds Classic Flang awareness to addFortranRuntime*, so that Classic Flang doesn't attempt to link with LLVM Flang libraries. Re-using the same methods as Clang and LLVM Flang also helps reduce downstream delta. A Classic Flang test is added to ensure that the linker command is constructed correctly. --- clang/lib/Driver/ToolChain.cpp | 32 ++++----------- clang/lib/Driver/ToolChains/CommonArgs.cpp | 18 ++++++++- clang/lib/Driver/ToolChains/CommonArgs.h | 3 ++ clang/lib/Driver/ToolChains/Darwin.cpp | 16 ++------ clang/lib/Driver/ToolChains/Gnu.cpp | 16 ++------ clang/lib/Driver/ToolChains/MSVC.cpp | 4 ++ clang/lib/Driver/ToolChains/MinGW.cpp | 4 ++ clang/test/Driver/flang/classic-flang.f95 | 46 ++++++++++++++++++++++ 8 files changed, 90 insertions(+), 49 deletions(-) diff --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp index 56ff77367570..420d7d0cbd9b 100644 --- a/clang/lib/Driver/ToolChain.cpp +++ b/clang/lib/Driver/ToolChain.cpp @@ -1042,42 +1042,26 @@ void ToolChain::AddCCKextLibArgs(const ArgList &Args, #ifdef ENABLE_CLASSIC_FLANG void ToolChain::AddFortranStdlibLibArgs(const ArgList &Args, - ArgStringList &CmdArgs) const { - bool staticFlangLibs = false; - bool useOpenMP = false; - + ArgStringList &CmdArgs) const { + bool StaticFlangLibs = false; if (Args.hasArg(options::OPT_staticFlangLibs)) { - for (auto *A: Args.filtered(options::OPT_staticFlangLibs)) { - A->claim(); - staticFlangLibs = true; - } - } - - Arg *A = Args.getLastArg(options::OPT_mp, options::OPT_nomp, - options::OPT_fopenmp, options::OPT_fno_openmp); - if (A && - (A->getOption().matches(options::OPT_mp) || - A->getOption().matches(options::OPT_fopenmp))) { - useOpenMP = true; + StaticFlangLibs = true; + Args.ClaimAllArgs(options::OPT_staticFlangLibs); } - if (staticFlangLibs) + if (StaticFlangLibs && !Args.hasArg(options::OPT_static)) CmdArgs.push_back("-Bstatic"); CmdArgs.push_back("-lflang"); CmdArgs.push_back("-lflangrti"); CmdArgs.push_back("-lpgmath"); - if (useOpenMP) - CmdArgs.push_back("-lomp"); - if (staticFlangLibs) + if (StaticFlangLibs && !Args.hasArg(options::OPT_static)) CmdArgs.push_back("-Bdynamic"); - CmdArgs.push_back("-lm"); + // Always link Fortran executables with pthreads. + CmdArgs.push_back("-lpthread"); if (!Triple.isOSDarwin()) CmdArgs.push_back("-lrt"); - - // Allways link Fortran executables with Pthreads - CmdArgs.push_back("-lpthread"); } #endif diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp index 723a4f7ca95d..b03a6b0405f6 100644 --- a/clang/lib/Driver/ToolChains/CommonArgs.cpp +++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp @@ -822,7 +822,11 @@ bool tools::addOpenMPRuntime(ArgStringList &CmdArgs, const ToolChain &TC, const ArgList &Args, bool ForceStaticHostRuntime, bool IsOffloadingHost, bool GompNeedsRT) { if (!Args.hasFlag(options::OPT_fopenmp, options::OPT_fopenmp_EQ, - options::OPT_fno_openmp, false)) + options::OPT_fno_openmp, false) +#ifdef ENABLE_CLASSIC_FLANG + && !Args.hasFlag(options::OPT_mp, options::OPT_nomp, false) +#endif + ) return false; Driver::OpenMPRuntimeKind RTKind = TC.getDriver().getOpenMPRuntime(Args); @@ -871,7 +875,16 @@ bool tools::addOpenMPRuntime(ArgStringList &CmdArgs, const ToolChain &TC, } void tools::addFortranRuntimeLibs(const ToolChain &TC, +#ifdef ENABLE_CLASSIC_FLANG + const llvm::opt::ArgList &Args, +#endif llvm::opt::ArgStringList &CmdArgs) { +#ifdef ENABLE_CLASSIC_FLANG + if (needFortranLibs(TC.getDriver(), Args)) + TC.AddFortranStdlibLibArgs(Args, CmdArgs); + else + Args.ClaimAllArgs(options::OPT_noFlangLibs); +#else if (TC.getTriple().isKnownWindowsMSVCEnvironment()) { CmdArgs.push_back("Fortran_main.lib"); CmdArgs.push_back("FortranRuntime.lib"); @@ -881,16 +894,19 @@ void tools::addFortranRuntimeLibs(const ToolChain &TC, CmdArgs.push_back("-lFortranRuntime"); CmdArgs.push_back("-lFortranDecimal"); } +#endif } void tools::addFortranRuntimeLibraryPath(const ToolChain &TC, const llvm::opt::ArgList &Args, ArgStringList &CmdArgs) { +#ifndef ENABLE_CLASSIC_FLANG // NOTE: Generating executables by Flang is considered an "experimental" // feature and hence this is guarded with a command line option. // TODO: Make this work unconditionally once Flang is mature enough. if (!Args.hasArg(options::OPT_flang_experimental_exec)) return; +#endif // Default to the /../lib directory. This works fine on the // platforms that we have tested so far. We will probably have to re-fine diff --git a/clang/lib/Driver/ToolChains/CommonArgs.h b/clang/lib/Driver/ToolChains/CommonArgs.h index 436d3f8f5a87..8ec7d7c7abc8 100644 --- a/clang/lib/Driver/ToolChains/CommonArgs.h +++ b/clang/lib/Driver/ToolChains/CommonArgs.h @@ -133,6 +133,9 @@ bool addOpenMPRuntime(llvm::opt::ArgStringList &CmdArgs, const ToolChain &TC, /// Adds Fortran runtime libraries to \p CmdArgs. void addFortranRuntimeLibs(const ToolChain &TC, +#ifdef ENABLE_CLASSIC_FLANG + const llvm::opt::ArgList &Args, +#endif llvm::opt::ArgStringList &CmdArgs); /// Adds the path for the Fortran runtime libraries to \p CmdArgs. diff --git a/clang/lib/Driver/ToolChains/Darwin.cpp b/clang/lib/Driver/ToolChains/Darwin.cpp index 13ec8894c021..ab442c3c0583 100644 --- a/clang/lib/Driver/ToolChains/Darwin.cpp +++ b/clang/lib/Driver/ToolChains/Darwin.cpp @@ -639,7 +639,11 @@ void darwin::Linker::ConstructJob(Compilation &C, const JobAction &JA, // to generate executables. if (getToolChain().getDriver().IsFlangMode()) { addFortranRuntimeLibraryPath(getToolChain(), Args, CmdArgs); +#ifdef ENABLE_CLASSIC_FLANG + addFortranRuntimeLibs(getToolChain(), Args, CmdArgs); +#else addFortranRuntimeLibs(getToolChain(), CmdArgs); +#endif } if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) @@ -678,18 +682,6 @@ void darwin::Linker::ConstructJob(Compilation &C, const JobAction &JA, if (getToolChain().ShouldLinkCXXStdlib(Args)) getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs); -#ifdef ENABLE_CLASSIC_FLANG - // Add Fortran runtime libraries - if (needFortranLibs(getToolChain().getDriver(), Args)) { - getToolChain().AddFortranStdlibLibArgs(Args, CmdArgs); - } else { - // Claim "no Flang libraries" arguments if any - for (auto Arg : Args.filtered(options::OPT_noFlangLibs)) { - Arg->claim(); - } - } -#endif - bool NoStdOrDefaultLibs = Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs); bool ForceLinkBuiltins = Args.hasArg(options::OPT_fapple_link_rtlib); diff --git a/clang/lib/Driver/ToolChains/Gnu.cpp b/clang/lib/Driver/ToolChains/Gnu.cpp index 69e34dfa3fed..484b6e1ad9a2 100644 --- a/clang/lib/Driver/ToolChains/Gnu.cpp +++ b/clang/lib/Driver/ToolChains/Gnu.cpp @@ -567,18 +567,6 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA, // The profile runtime also needs access to system libraries. getToolChain().addProfileRTLibs(Args, CmdArgs); -#ifdef ENABLE_CLASSIC_FLANG - // Add Fortran runtime libraries - if (needFortranLibs(D, Args)) { - ToolChain.AddFortranStdlibLibArgs(Args, CmdArgs); - } else { - // Claim "no Flang libraries" arguments if any - for (auto Arg : Args.filtered(options::OPT_noFlangLibs)) { - Arg->claim(); - } - } -#endif - if (D.CCCIsCXX() && !Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs, options::OPT_r)) { @@ -610,7 +598,11 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA, // AddRuntTimeLibs). if (D.IsFlangMode()) { addFortranRuntimeLibraryPath(ToolChain, Args, CmdArgs); +#ifdef ENABLE_CLASSIC_FLANG + addFortranRuntimeLibs(ToolChain, Args, CmdArgs); +#else addFortranRuntimeLibs(ToolChain, CmdArgs); +#endif CmdArgs.push_back("-lm"); } diff --git a/clang/lib/Driver/ToolChains/MSVC.cpp b/clang/lib/Driver/ToolChains/MSVC.cpp index 14ebe38ee191..3441428793b0 100644 --- a/clang/lib/Driver/ToolChains/MSVC.cpp +++ b/clang/lib/Driver/ToolChains/MSVC.cpp @@ -132,7 +132,11 @@ void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA, if (C.getDriver().IsFlangMode()) { addFortranRuntimeLibraryPath(TC, Args, CmdArgs); +#ifdef ENABLE_CLASSIC_FLANG + addFortranRuntimeLibs(TC, Args, CmdArgs); +#else addFortranRuntimeLibs(TC, CmdArgs); +#endif // Inform the MSVC linker that we're generating a console application, i.e. // one with `main` as the "user-defined" entry point. The `main` function is diff --git a/clang/lib/Driver/ToolChains/MinGW.cpp b/clang/lib/Driver/ToolChains/MinGW.cpp index ae7c4c56bf9e..83a1980c5208 100644 --- a/clang/lib/Driver/ToolChains/MinGW.cpp +++ b/clang/lib/Driver/ToolChains/MinGW.cpp @@ -220,7 +220,11 @@ void tools::MinGW::Linker::ConstructJob(Compilation &C, const JobAction &JA, if (C.getDriver().IsFlangMode()) { addFortranRuntimeLibraryPath(TC, Args, CmdArgs); +#ifdef ENABLE_CLASSIC_FLANG + addFortranRuntimeLibs(TC, Args, CmdArgs); +#else addFortranRuntimeLibs(TC, CmdArgs); +#endif } // TODO: Add profile stuff here diff --git a/clang/test/Driver/flang/classic-flang.f95 b/clang/test/Driver/flang/classic-flang.f95 index 6fce9c61713c..bc51c6e0c380 100644 --- a/clang/test/Driver/flang/classic-flang.f95 +++ b/clang/test/Driver/flang/classic-flang.f95 @@ -41,3 +41,49 @@ ! CHECK-ASM-SAME: "-o" "classic-flang.s" ! CHECK-ASM-SAME: "-x" "ir" ! CHECK-ASM-SAME: [[LLFILE]] + +! Check that the linker job is given the correct libraries and library paths. + +! RUN: %flang -target x86_64-linux-gnu -ccc-install-dir %S/../Inputs/basic_linux_tree/usr/bin -mp \ +! RUN: %s -lfoo -### 2>&1 | FileCheck --check-prefixes=CHECK-LD,CHECK-DYNAMIC-FLANG,CHECK-DYNAMIC-OMP %s +! RUN: %flang -target x86_64-linux-gnu -ccc-install-dir %S/../Inputs/basic_linux_tree/usr/bin -mp -nomp \ +! RUN: %s -lfoo -### 2>&1 | FileCheck --check-prefixes=CHECK-LD,CHECK-DYNAMIC-FLANG,CHECK-NO-OMP %s +! RUN: %flang -target x86_64-linux-gnu -ccc-install-dir %S/../Inputs/basic_linux_tree/usr/bin -fopenmp \ +! RUN: %s -lfoo -### 2>&1 | FileCheck --check-prefixes=CHECK-LD,CHECK-DYNAMIC-FLANG,CHECK-DYNAMIC-OMP %s +! RUN: %flang -target x86_64-linux-gnu -ccc-install-dir %S/../Inputs/basic_linux_tree/usr/bin -fopenmp -fno-openmp \ +! RUN: %s -lfoo -### 2>&1 | FileCheck --check-prefixes=CHECK-LD,CHECK-DYNAMIC-FLANG,CHECK-NO-OMP %s +! RUN: %flang -target x86_64-linux-gnu -ccc-install-dir %S/../Inputs/basic_linux_tree/usr/bin -fopenmp -static-openmp \ +! RUN: %s -lfoo -### 2>&1 | FileCheck --check-prefixes=CHECK-LD,CHECK-DYNAMIC-FLANG,CHECK-STATIC-OMP %s +! RUN: %flang -target x86_64-linux-gnu -ccc-install-dir %S/../Inputs/basic_linux_tree/usr/bin -fopenmp -static-flang-libs \ +! RUN: %s -lfoo -### 2>&1 | FileCheck --check-prefixes=CHECK-LD,CHECK-STATIC-FLANG,CHECK-DYNAMIC-OMP %s +! RUN: %flang -target x86_64-linux-gnu -ccc-install-dir %S/../Inputs/basic_linux_tree/usr/bin -static-flang-libs \ +! RUN: %s -lfoo -### 2>&1 | FileCheck --check-prefixes=CHECK-LD,CHECK-STATIC-FLANG,CHECK-NO-OMP %s + +! CHECK-LD: "{{.*}}ld" +! CHECK-LD-NOT: "-static" +! CHECK-LD: "{{[^"]*}}classic-flang-{{[^ ]*}}.o" "-lflangmain" "-lfoo" "-L{{[^ ]*}}/basic_linux_tree/usr/lib" +! CHECK-DYNAMIC-FLANG-NOT: "-Bstatic" +! CHECK-DYNAMIC-FLANG: "-lflang" "-lflangrti" "-lpgmath" "-lpthread" "-lrt" "-lm" +! CHECK-DYNAMIC-FLANG-NOT: "-Bdynamic" +! CHECK-STATIC-FLANG: "-Bstatic" "-lflang" "-lflangrti" "-lpgmath" "-Bdynamic" "-lpthread" "-lrt" "-lm" +! CHECK-DYNAMIC-OMP-NOT: "-Bstatic" +! CHECK-DYNAMIC-OMP: "-lomp" "-rpath" "{{[^ ]*}}/basic_linux_tree/usr/lib" +! CHECK-DYNAMIC-OMP-NOT: "-Bdynamic" +! CHECK-STATIC-OMP: "-Bstatic" "-lomp" "-Bdynamic" "-rpath" "{{[^ ]*}}/basic_linux_tree/usr/lib" +! CHECK-NO-OMP-NOT: "-lomp" + +! RUN: %flang -target x86_64-linux-gnu -ccc-install-dir %S/../Inputs/basic_linux_tree/usr/bin -static -static-flang-libs \ +! RUN: %s -lfoo -### 2>&1 | FileCheck --check-prefixes=CHECK-LD-STATIC,CHECK-NO-OMP %s +! RUN: %flang -target x86_64-linux-gnu -ccc-install-dir %S/../Inputs/basic_linux_tree/usr/bin -static -fopenmp \ +! RUN: %s -lfoo -### 2>&1 | FileCheck --check-prefixes=CHECK-LD-STATIC,CHECK-STATIC-BOTH %s +! RUN: %flang -target x86_64-linux-gnu -ccc-install-dir %S/../Inputs/basic_linux_tree/usr/bin -static -fopenmp -static-openmp \ +! RUN: %s -lfoo -### 2>&1 | FileCheck --check-prefixes=CHECK-LD-STATIC,CHECK-STATIC-BOTH %s +! CHECK-LD-STATIC: "{{.*}}ld" +! CHECK-LD-STATIC: "-static" "-o" "a.out" +! CHECK-LD-STATIC: "{{[^"]*}}classic-flang-{{[^ ]*}}.o" "-lflangmain" "-lfoo" "-L{{[^ ]*}}/basic_linux_tree/usr/lib" +! CHECK-LD-STATIC-NOT: "-Bstatic" +! CHECK-LD-STATIC: "-lflang" "-lflangrti" "-lpgmath" "-lpthread" "-lrt" "-lm" +! CHECK-LD-STATIC-NOT: "-Bdynamic" +! CHECK-STATIC-BOTH-NOT: "-Bstatic" +! CHECK-STATIC-BOTH: "-lomp" +! CHECK-STATIC-BOTH-NOT: "-Bdynamic" -- Gitee From 89bf9aaec5cdaa89fae6ef24049840990e6f1573 Mon Sep 17 00:00:00 2001 From: Bryan Chan Date: Wed, 7 Sep 2022 15:48:40 -0400 Subject: [PATCH 28/33] [workflows] Allow GitHub actions in the classic-flang-llvm-project fork LLVM 15 added 'ignore-forks: true' to the GitHub action triggers, which prevents the actions from running in the classic-flang-llvm-project repo. This patch undoes the setting. --- .github/workflows/clang-tests.yml | 2 -- .github/workflows/llvm-tests.yml | 2 -- 2 files changed, 4 deletions(-) diff --git a/.github/workflows/clang-tests.yml b/.github/workflows/clang-tests.yml index f8d5fd8f4666..1af3b41ba087 100644 --- a/.github/workflows/clang-tests.yml +++ b/.github/workflows/clang-tests.yml @@ -3,7 +3,6 @@ name: Clang Tests on: workflow_dispatch: push: - ignore-forks: true branches: - 'release/**' paths: @@ -12,7 +11,6 @@ on: - '.github/workflows/llvm-project-tests.yml' - '!llvm/**' pull_request: - ignore-forks: true branches: - 'release/**' paths: diff --git a/.github/workflows/llvm-tests.yml b/.github/workflows/llvm-tests.yml index 7264c62ce134..fbff885122f2 100644 --- a/.github/workflows/llvm-tests.yml +++ b/.github/workflows/llvm-tests.yml @@ -3,7 +3,6 @@ name: LLVM Tests on: workflow_dispatch: push: - ignore-forks: true branches: - 'release/**' paths: @@ -11,7 +10,6 @@ on: - '.github/workflows/llvm-tests.yml' - '.github/workflows/llvm-project-tests.yml' pull_request: - ignore-forks: true branches: - 'release/**' paths: -- Gitee From bc3b9f85292cfb251527a7ad756f723e255b7757 Mon Sep 17 00:00:00 2001 From: Bryan Chan Date: Fri, 9 Sep 2022 08:44:33 -0400 Subject: [PATCH 29/33] [workflows] Update branch filter to allow actions on all 'release_*x' branches By changing the branch filter from an explicit list to a glob, this commit hopes to reduce future maintenance burden (as long as we continue to use the same branch naming convention). --- .github/workflows/clang-tests.yml | 4 ++-- .github/workflows/flang-tests.yml | 3 ++- .github/workflows/llvm-tests.yml | 4 ++-- .github/workflows/pre-compile_llvm.yml | 3 ++- 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/.github/workflows/clang-tests.yml b/.github/workflows/clang-tests.yml index 1af3b41ba087..19c0a394de49 100644 --- a/.github/workflows/clang-tests.yml +++ b/.github/workflows/clang-tests.yml @@ -4,7 +4,7 @@ on: workflow_dispatch: push: branches: - - 'release/**' + - 'release_*x' paths: - 'clang/**' - '.github/workflows/clang-tests.yml' @@ -12,7 +12,7 @@ on: - '!llvm/**' pull_request: branches: - - 'release/**' + - 'release_*x' paths: - 'clang/**' - '.github/workflows/clang-tests.yml' diff --git a/.github/workflows/flang-tests.yml b/.github/workflows/flang-tests.yml index 410ba05290a7..c7ce689451da 100644 --- a/.github/workflows/flang-tests.yml +++ b/.github/workflows/flang-tests.yml @@ -2,7 +2,8 @@ name: Build and test Flang on: pull_request: - branches: [ release_11x, release_12x, release_13x, release_14x ] + branches: + - 'release_*x' jobs: build: diff --git a/.github/workflows/llvm-tests.yml b/.github/workflows/llvm-tests.yml index fbff885122f2..d0ddfeca1e57 100644 --- a/.github/workflows/llvm-tests.yml +++ b/.github/workflows/llvm-tests.yml @@ -4,14 +4,14 @@ on: workflow_dispatch: push: branches: - - 'release/**' + - 'release_*x' paths: - 'llvm/**' - '.github/workflows/llvm-tests.yml' - '.github/workflows/llvm-project-tests.yml' pull_request: branches: - - 'release/**' + - 'release_*x' paths: - 'llvm/**' - '.github/workflows/llvm-tests.yml' diff --git a/.github/workflows/pre-compile_llvm.yml b/.github/workflows/pre-compile_llvm.yml index 7cb4b8ed72bd..98b54ed41f98 100644 --- a/.github/workflows/pre-compile_llvm.yml +++ b/.github/workflows/pre-compile_llvm.yml @@ -3,7 +3,8 @@ name: Pre-compile llvm on: workflow_dispatch: push: - branches: [ release_11x, release_12x, release_13x, release_14x ] + branches: + - 'release_*x' jobs: build: -- Gitee From 4ae6774fea088c7c09e013a1f6c573d3ebbb4e09 Mon Sep 17 00:00:00 2001 From: Bryan Chan Date: Thu, 8 Sep 2022 09:35:31 -0400 Subject: [PATCH 30/33] [OpenMP] Exclude a test that fails on smaller GitHub runners --- openmp/runtime/test/ompt/teams/distribute_dispatch.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/openmp/runtime/test/ompt/teams/distribute_dispatch.c b/openmp/runtime/test/ompt/teams/distribute_dispatch.c index 9435ff1a9fea..cfbe791a73d8 100644 --- a/openmp/runtime/test/ompt/teams/distribute_dispatch.c +++ b/openmp/runtime/test/ompt/teams/distribute_dispatch.c @@ -1,5 +1,10 @@ // RUN: %libomp-compile-and-run | %sort-threads | FileCheck %s // REQUIRES: ompt + +// This test expects 4 teams of 1 thread each to be created, and fails +// on CI runners with insufficient resources. +// UNSUPPORTED: linux + #include "callback.h" #define WORK_SIZE 64 -- Gitee From 15189c335bc101e99a93c34807357dfab51e8e0e Mon Sep 17 00:00:00 2001 From: Bryan Chan Date: Tue, 18 Oct 2022 17:11:07 -0400 Subject: [PATCH 31/33] [workflows] Add AArch64 build job Unlike their flang counterparts, classic-flang-llvm-project PRs did not have any AArch64 workflows. So problems with a PR may remain hidden until another PR is submitted to the flang repo and fails the AArch64 workflow there. This patch adds the missing build job. --- .github/workflows/flang-arm64-tests.yml | 70 +++++++++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 .github/workflows/flang-arm64-tests.yml diff --git a/.github/workflows/flang-arm64-tests.yml b/.github/workflows/flang-arm64-tests.yml new file mode 100644 index 000000000000..bd85c550f008 --- /dev/null +++ b/.github/workflows/flang-arm64-tests.yml @@ -0,0 +1,70 @@ +name: Build and test Flang + +on: + pull_request: + branches: + - 'release_*x' + +jobs: + build: + runs-on: self-hosted + env: + build_path: /home/github + install_prefix: /home/github/usr/local + container: + image: ghcr.io/${{ github.repository_owner}}/ubuntu20-flang-${{ github.base_ref }}:latest + credentials: + username: github + strategy: + matrix: + target: [AArch64] + cc: [clang] + cpp: [clang++] + version: [10, 11] + include: + - target: AArch64 + cc: gcc + cpp: g++ + version: 10 + + steps: + - name: Check tools + run: | + git --version + cmake --version + make --version + ${{ matrix.cc }}-${{ matrix.version }} --version + ${{ matrix.cpp }}-${{ matrix.version }} --version + + - name: Manual checkout to build in user's home dir (pull_request) + run: | + cd ${{ env.build_path }} + git clone https://github.com/flang-compiler/classic-flang-llvm-project.git + cd classic-flang-llvm-project + git fetch origin ${{github.ref}}:pr_branch + git checkout pr_branch + + - name: Build and install llvm + run: | + cd ${{ env.build_path }}/classic-flang-llvm-project + ./build-llvm-project.sh -t ${{ matrix.target }} -p ${{ env.install_prefix }} -a /usr/bin/${{ matrix.cc }}-${{ matrix.version }} -b /usr/bin/${{ matrix.cpp }}-${{ matrix.version }} -n $(nproc) -i -v + + - name: Checkout flang + run: | + cd ${{ env.build_path }} + git clone --depth 1 --single-branch --branch master https://github.com/flang-compiler/flang.git + + - name: Build and install libpgmath & flang + run: | + cd ${{ env.build_path }}/flang + ./build-flang.sh -t ${{ matrix.target }} -p ${{ env.install_prefix }} -n $(nproc) + + - name: Copy llvm-lit + run: | + cd ${{ env.build_path }}/flang + cp ${{ env.build_path }}/classic-flang-llvm-project/build/bin/llvm-lit build/bin/. + + - name: Test flang + run: | + cd ${{ env.build_path }}/flang/build + make check-all -- Gitee From 2a5041cf9d09ba4ab1fa6ef1a559b0448fba551d Mon Sep 17 00:00:00 2001 From: Bryan Chan Date: Thu, 3 Nov 2022 08:57:43 -0400 Subject: [PATCH 32/33] [AsmPrinter] Delete dead code; NFC Delete some snippets that had been commented out since commit a10f592d3b027 in release_13x. --- llvm/lib/CodeGen/AsmPrinter/DebugLocEntry.h | 35 ----------- llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp | 70 --------------------- llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h | 8 --- 3 files changed, 113 deletions(-) diff --git a/llvm/lib/CodeGen/AsmPrinter/DebugLocEntry.h b/llvm/lib/CodeGen/AsmPrinter/DebugLocEntry.h index e2b99d523f27..185ee92777bf 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DebugLocEntry.h +++ b/llvm/lib/CodeGen/AsmPrinter/DebugLocEntry.h @@ -214,15 +214,6 @@ public: LLVM_DUMP_METHOD void dump() const { for (const DbgValueLocEntry &DV : ValueLocEntries) DV.dump(); -// if (isLocation()) { -// llvm::dbgs() << "Loc = { reg=" << Loc.getReg() << " "; -// if (Loc.isIndirect()) -// llvm::dbgs() << "+0"; -// llvm::dbgs() << "} "; -// } else if (isConstantInt()) -// Constant.CIP->dump(); -// else if (isConstantFP()) -// Constant.CFP->dump(); if (Expression) Expression->dump(); } @@ -290,9 +281,6 @@ public: DebugLocStream::ListBuilder &List, const DIBasicType *BT, DwarfCompileUnit &TheCU); - -// void finalize(const AsmPrinter &AP, DebugLocStream::ListBuilder &List, -// const DIStringType *ST, DwarfCompileUnit &TheCU); }; /// Compare two DbgValueLocEntries for equality. @@ -321,29 +309,6 @@ inline bool operator==(const DbgValueLoc &A, const DbgValueLoc &B) { A.Expression == B.Expression && A.IsVariadic == B.IsVariadic; } -//inline bool operator==(const DbgValueLoc &A, -// const DbgValueLoc &B) { -// if (A.EntryKind != B.EntryKind) -// return false; -// -// if (A.Expression != B.Expression) -// return false; -// -// switch (A.EntryKind) { -// case DbgValueLoc::E_Location: -// return A.Loc == B.Loc; -// case DbgValueLoc::E_TargetIndexLocation: -// return A.TIL == B.TIL; -// case DbgValueLoc::E_Integer: -// return A.Constant.Int == B.Constant.Int; -// case DbgValueLoc::E_ConstantFP: -// return A.Constant.CFP == B.Constant.CFP; -// case DbgValueLoc::E_ConstantInt: -// return A.Constant.CIP == B.Constant.CIP; -// } -// llvm_unreachable("unhandled EntryKind"); -//} - /// Compare two fragments based on their offset. inline bool operator<(const DbgValueLoc &A, const DbgValueLoc &B) { diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp index c8cbbf6eb464..54af14429907 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -1826,28 +1826,10 @@ DbgEntity *DwarfDebug::createConcreteEntity(DwarfCompileUnit &TheCU, return ConcreteEntities.back().get(); } -#if 0 -void DwarfDebug::populateDependentTypeMap() { - for (const auto &I : DbgValues) { - InlinedEntity IV = I.first; - if (I.second.empty()) - continue; - if (const DIVariable *DIV = dyn_cast(IV.first)) { - if (const DIStringType *ST = dyn_cast( - static_cast(DIV->getType()))) - if (const DIVariable *LV = ST->getStringLength()) - VariableInDependentType[LV] = ST; - } - } -} -#endif - // Find variables for each lexical scope. void DwarfDebug::collectEntityInfo(DwarfCompileUnit &TheCU, const DISubprogram *SP, DenseSet &Processed) { -// clearDependentTracking(); -// populateDependentTypeMap(); // Grab the variable info that was squirreled away in the MMI side-table. collectVariableInfoFromMFTable(TheCU, Processed); @@ -1866,11 +1848,6 @@ void DwarfDebug::collectEntityInfo(DwarfCompileUnit &TheCU, LexicalScope *Scope = nullptr; const DILocalVariable *LocalVar = cast(IV.first); -#if 0 - const DILocalVariable *LocalVar = dyn_cast(IV.first); - if (!LocalVar) - continue; -#endif if (const DILocation *IA = IV.second) Scope = LScopes.findInlinedScope(LocalVar->getScope(), IA); else @@ -1929,24 +1906,6 @@ void DwarfDebug::collectEntityInfo(DwarfCompileUnit &TheCU, // Finalize the entry by lowering it into a DWARF bytestream. for (auto &Entry : Entries) Entry.finalize(*Asm, List, BT, TheCU); -#if 0 - List.finalize(); - - if (VariableInDependentType.count(LocalVar)) { - const DIType *DT = VariableInDependentType[LocalVar]; - if (const DIStringType *ST = dyn_cast(DT)) { - unsigned Offset; - DbgVariable TVar = {LocalVar, IV.second}; - DebugLocStream::ListBuilder LB(DebugLocs, TheCU, *Asm, TVar, *MInsn); - for (auto &Entry : Entries) - Entry.finalize(*Asm, LB, ST, TheCU); - LB.finalize(); - Offset = TVar.getDebugLocListIndex(); - if (Offset != ~0u) - addStringTypeLoc(ST, Offset); - } - } -#endif } // For each InlinedEntity collected from DBG_LABEL instructions, convert to @@ -2718,35 +2677,6 @@ void DebugLocEntry::finalize(const AsmPrinter &AP, List.setTagOffset(*DwarfExpr.TagOffset); } -#if 0 -inline static DbgValueLoc mkDbgValueLoc(const DIExpression *expr, - DbgValueLoc &value) { - if (value.isInt()) - return DbgValueLoc(expr, value.getInt()); - if (value.isLocation()) - return DbgValueLoc(expr, value.getLoc()); - if (value.isConstantInt()) - return DbgValueLoc(expr, value.getConstantInt()); - assert(value.isConstantFP()); - return DbgValueLoc(expr, value.getConstantFP()); -} - -void DebugLocEntry::finalize(const AsmPrinter &AP, - DebugLocStream::ListBuilder &List, - const DIStringType *ST, - DwarfCompileUnit &TheCU) { - DebugLocStream::EntryBuilder Entry(List, Begin, End); - BufferByteStreamer Streamer = Entry.getStreamer(); - DebugLocDwarfExpression DwarfExpr(AP.getDwarfVersion(), Streamer, TheCU); - DbgValueLoc &Value = Values[0]; - assert(!Value.isFragment()); - assert(Values.size() == 1 && "only fragments may have >1 value"); - Value = mkDbgValueLoc(ST->getStringLengthExp(), Value); - DwarfDebug::emitDebugLocValue(AP, nullptr, Value, DwarfExpr); - DwarfExpr.finalize(); -} -#endif - void DwarfDebug::emitDebugLocEntryLocation(const DebugLocStream::Entry &Entry, const DwarfCompileUnit *CU) { // Emit the size. diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h index b1bc16ee57a8..c249f812042f 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h @@ -628,14 +628,6 @@ private: /// Emit the reference to the section. void emitSectionReference(const DwarfCompileUnit &CU); -#if 0 - /// Populate dependent type variable map - void populateDependentTypeMap(); -#endif - - /// Clear dependent type tracking map - void clearDependentTracking() { VariableInDependentType.clear(); } - protected: /// Gather pre-function debug information. void beginFunctionImpl(const MachineFunction *MF) override; -- Gitee From 20893f071a1300bd0f8a7c0a9b7aecf8b89be1bb Mon Sep 17 00:00:00 2001 From: Bryan Chan Date: Thu, 3 Nov 2022 09:06:01 -0400 Subject: [PATCH 33/33] [workflows] Delete misleading pull request template Upstream llvm-project repository does not accept pull requests, but our fork does. --- .github/PULL_REQUEST_TEMPLATE.md | 5 ----- 1 file changed, 5 deletions(-) delete mode 100644 .github/PULL_REQUEST_TEMPLATE.md diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md deleted file mode 100644 index a3d33bdb4d43..000000000000 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ /dev/null @@ -1,5 +0,0 @@ -# **DO NOT FILE A PULL REQUEST** - -This repository does not accept pull requests. Please follow http://llvm.org/docs/Contributing.html#how-to-submit-a-patch for contribution to LLVM. - -# **DO NOT FILE A PULL REQUEST** -- Gitee